First half of C++17's splicing maps and sets

This commit adds a node handle type, (located in __node_handle), and adds
extract() and insert() members to all map and set types, as well as their
implementations in __tree and __hash_table.

The second half of this feature is adding merge() members, which splice nodes
in bulk from one container into another. This will be committed in a follow-up.

Differential revision: https://reviews.llvm.org/D46845

llvm-svn: 338472
This commit is contained in:
Erik Pilkington 2018-08-01 01:33:38 +00:00
parent 9057546c5b
commit b0386a515b
43 changed files with 3215 additions and 10 deletions

View File

@ -11,6 +11,7 @@ set(files
__libcpp_version
__locale
__mutex_base
__node_handle
__nullptr
__split_buffer
__sso_allocator

View File

@ -859,6 +859,17 @@ public:
template <class> friend class __hash_map_node_destructor;
};
#if _LIBCPP_STD_VER > 14
template <class _NodeType, class _Alloc>
struct __generic_container_node_destructor;
template <class _Tp, class _VoidPtr, class _Alloc>
struct __generic_container_node_destructor<__hash_node<_Tp, _VoidPtr>, _Alloc>
: __hash_node_destructor<_Alloc>
{
using __hash_node_destructor<_Alloc>::__hash_node_destructor;
};
#endif
#ifndef _LIBCPP_CXX03_LANG
template <class _Key, class _Hash, class _Equal, class _Alloc>
@ -1151,6 +1162,30 @@ public:
return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x);
}
#if _LIBCPP_STD_VER > 14
template <class _NodeHandle, class _InsertReturnType>
_LIBCPP_INLINE_VISIBILITY
_InsertReturnType __node_handle_insert_unique(_NodeHandle&& __nh);
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
iterator __node_handle_insert_unique(const_iterator __hint,
_NodeHandle&& __nh);
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
iterator __node_handle_insert_multi(_NodeHandle&& __nh);
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
iterator __node_handle_insert_multi(const_iterator __hint, _NodeHandle&& __nh);
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
_NodeHandle __node_handle_extract(key_type const& __key);
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
_NodeHandle __node_handle_extract(const_iterator __it);
#endif
void clear() _NOEXCEPT;
void rehash(size_type __n);
_LIBCPP_INLINE_VISIBILITY void reserve(size_type __n)
@ -2126,6 +2161,91 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
#endif // _LIBCPP_CXX03_LANG
#if _LIBCPP_STD_VER > 14
template <class _Tp, class _Hash, class _Equal, class _Alloc>
template <class _NodeHandle, class _InsertReturnType>
_LIBCPP_INLINE_VISIBILITY
_InsertReturnType
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(
_NodeHandle&& __nh)
{
if (__nh.empty())
return _InsertReturnType{end(), false, _NodeHandle()};
pair<iterator, bool> __result = __node_insert_unique(__nh.__ptr_);
if (__result.second)
__nh.__release();
return _InsertReturnType{__result.first, __result.second, _VSTD::move(__nh)};
}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(
const_iterator, _NodeHandle&& __nh)
{
if (__nh.empty())
return end();
pair<iterator, bool> __result = __node_insert_unique(__nh.__ptr_);
if (__result.second)
__nh.__release();
return __result.first;
}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
_NodeHandle
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(
key_type const& __key)
{
iterator __i = find(__key);
if (__i == end())
return _NodeHandle();
return __node_handle_extract<_NodeHandle>(__i);
}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
_NodeHandle
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(
const_iterator __p)
{
allocator_type __alloc(__node_alloc());
return _NodeHandle(remove(__p).release(), __alloc);
}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(
_NodeHandle&& __nh)
{
if (__nh.empty())
return end();
iterator __result = __node_insert_multi(__nh.__ptr_);
__nh.__release();
return __result;
}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(
const_iterator __hint, _NodeHandle&& __nh)
{
if (__nh.empty())
return end();
iterator __result = __node_insert_multi(__hint, __nh.__ptr_);
__nh.__release();
return __result;
}
#endif // _LIBCPP_STD_VER > 14
template <class _Tp, class _Hash, class _Equal, class _Alloc>
void
__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n)

View File

@ -0,0 +1,212 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___NODE_HANDLE
#define _LIBCPP___NODE_HANDLE
#include <__config>
#include <memory>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER > 14
#define __cpp_lib_node_extract 201606L
// Specialized in __tree & __hash_table for their _NodeType.
template <class _NodeType, class _Alloc>
struct __generic_container_node_destructor;
template <class _NodeType, class _Alloc,
template <class, class> class _MapOrSetSpecifics>
class _LIBCPP_TEMPLATE_VIS __basic_node_handle
: public _MapOrSetSpecifics<
_NodeType,
__basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>>
{
template <class _Tp, class _Compare, class _Allocator>
friend class __tree;
template <class _Tp, class _Hash, class _Equal, class _Allocator>
friend class __hash_table;
friend struct _MapOrSetSpecifics<
_NodeType, __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>>;
typedef allocator_traits<_Alloc> __alloc_traits;
typedef typename __rebind_pointer<typename __alloc_traits::void_pointer,
_NodeType>::type
__node_pointer_type;
public:
typedef _Alloc allocator_type;
private:
__node_pointer_type __ptr_ = nullptr;
optional<allocator_type> __alloc_;
_LIBCPP_INLINE_VISIBILITY
void __release()
{
__ptr_ = nullptr;
__alloc_ = _VSTD::nullopt;
}
_LIBCPP_INLINE_VISIBILITY
void __destroy_node_pointer()
{
if (__ptr_ != nullptr)
{
typedef typename __allocator_traits_rebind<
allocator_type, _NodeType>::type __node_alloc_type;
__node_alloc_type __alloc(*__alloc_);
__generic_container_node_destructor<_NodeType, __node_alloc_type>(
__alloc, true)(__ptr_);
__ptr_ = nullptr;
}
}
_LIBCPP_INLINE_VISIBILITY
__basic_node_handle(__node_pointer_type __ptr,
allocator_type const& __alloc)
: __ptr_(__ptr), __alloc_(__alloc)
{
}
public:
_LIBCPP_INLINE_VISIBILITY
__basic_node_handle() = default;
_LIBCPP_INLINE_VISIBILITY
__basic_node_handle(__basic_node_handle&& __other) noexcept
: __ptr_(__other.__ptr_),
__alloc_(_VSTD::move(__other.__alloc_))
{
__other.__ptr_ = nullptr;
__other.__alloc_ = _VSTD::nullopt;
}
_LIBCPP_INLINE_VISIBILITY
__basic_node_handle& operator=(__basic_node_handle&& __other)
{
_LIBCPP_ASSERT(
__alloc_ == _VSTD::nullopt ||
__alloc_traits::propagate_on_container_move_assignment::value ||
__alloc_ == __other.__alloc_,
"node_type with incompatible allocator passed to "
"node_type::operator=(node_type&&)");
__destroy_node_pointer();
__ptr_ = __other.__ptr_;
if (__alloc_traits::propagate_on_container_move_assignment::value ||
__alloc_ == _VSTD::nullopt)
__alloc_ = _VSTD::move(__other.__alloc_);
__other.__ptr_ = nullptr;
__other.__alloc_ = _VSTD::nullopt;
return *this;
}
_LIBCPP_INLINE_VISIBILITY
allocator_type get_allocator() const { return *__alloc_; }
_LIBCPP_INLINE_VISIBILITY
explicit operator bool() const { return __ptr_ != nullptr; }
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
bool empty() const { return __ptr_ == nullptr; }
_LIBCPP_INLINE_VISIBILITY
void swap(__basic_node_handle& __other) noexcept(
__alloc_traits::propagate_on_container_swap::value ||
__alloc_traits::is_always_equal::value)
{
using _VSTD::swap;
swap(__ptr_, __other.__ptr_);
if (__alloc_traits::propagate_on_container_swap::value ||
__alloc_ == _VSTD::nullopt || __other.__alloc_ == _VSTD::nullopt)
swap(__alloc_, __other.__alloc_);
}
_LIBCPP_INLINE_VISIBILITY
friend void swap(__basic_node_handle& __a, __basic_node_handle& __b)
noexcept(noexcept(__a.swap(__b))) { __a.swap(__b); }
_LIBCPP_INLINE_VISIBILITY
~__basic_node_handle()
{
__destroy_node_pointer();
}
};
template <class _NodeType, class _Derived>
struct __set_node_handle_specifics
{
typedef typename _NodeType::__node_value_type value_type;
_LIBCPP_INLINE_VISIBILITY
value_type& value() const
{
return static_cast<_Derived const*>(this)->__ptr_->__value_;
}
};
template <class _NodeType, class _Derived>
struct __map_node_handle_specifics
{
typedef typename _NodeType::__node_value_type::key_type key_type;
typedef typename _NodeType::__node_value_type::mapped_type mapped_type;
_LIBCPP_INLINE_VISIBILITY
key_type& key() const
{
return static_cast<_Derived const*>(this)->
__ptr_->__value_.__ref().first;
}
_LIBCPP_INLINE_VISIBILITY
mapped_type& mapped() const
{
return static_cast<_Derived const*>(this)->
__ptr_->__value_.__ref().second;
}
};
template <class _NodeType, class _Alloc>
using __set_node_handle =
__basic_node_handle< _NodeType, _Alloc, __set_node_handle_specifics>;
template <class _NodeType, class _Alloc>
using __map_node_handle =
__basic_node_handle< _NodeType, _Alloc, __map_node_handle_specifics>;
template <class _Iterator, class _NodeType>
_LIBCPP_TEMPLATE_VIS
struct __insert_return_type
{
_Iterator position;
bool inserted;
_NodeType node;
};
#endif // _LIBCPP_STD_VER > 14
_LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif

View File

@ -796,6 +796,16 @@ public:
template <class> friend class __map_node_destructor;
};
#if _LIBCPP_STD_VER > 14
template <class _NodeType, class _Alloc>
struct __generic_container_node_destructor;
template <class _Tp, class _VoidPtr, class _Alloc>
struct __generic_container_node_destructor<__tree_node<_Tp, _VoidPtr>, _Alloc>
: __tree_node_destructor<_Alloc>
{
using __tree_node_destructor<_Alloc>::__tree_node_destructor;
};
#endif
template <class _Tp, class _NodePtr, class _DiffType>
class _LIBCPP_TEMPLATE_VIS __tree_iterator
@ -1338,6 +1348,33 @@ public:
iterator __node_insert_multi(__node_pointer __nd);
iterator __node_insert_multi(const_iterator __p, __node_pointer __nd);
_LIBCPP_INLINE_VISIBILITY iterator __remove_node_pointer(__node_pointer);
#if _LIBCPP_STD_VER > 14
template <class _NodeHandle, class _InsertReturnType>
_LIBCPP_INLINE_VISIBILITY
_InsertReturnType __node_handle_insert_unique(_NodeHandle&&);
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
iterator __node_handle_insert_unique(const_iterator, _NodeHandle&&);
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
iterator __node_handle_insert_multi(_NodeHandle&&);
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
iterator __node_handle_insert_multi(const_iterator, _NodeHandle&&);
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
_NodeHandle __node_handle_extract(key_type const&);
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
_NodeHandle __node_handle_extract(const_iterator);
#endif
iterator erase(const_iterator __p);
iterator erase(const_iterator __f, const_iterator __l);
template <class _Key>
@ -2345,19 +2382,140 @@ __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p,
return iterator(__nd);
}
template <class _Tp, class _Compare, class _Allocator>
typename __tree<_Tp, _Compare, _Allocator>::iterator
__tree<_Tp, _Compare, _Allocator>::__remove_node_pointer(__node_pointer __ptr)
{
iterator __r(__ptr);
++__r;
if (__begin_node() == __ptr)
__begin_node() = __r.__ptr_;
--size();
__tree_remove(__end_node()->__left_,
static_cast<__node_base_pointer>(__ptr));
return __r;
}
#if _LIBCPP_STD_VER > 14
template <class _Tp, class _Compare, class _Allocator>
template <class _NodeHandle, class _InsertReturnType>
_LIBCPP_INLINE_VISIBILITY
_InsertReturnType
__tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(
_NodeHandle&& __nh)
{
if (__nh.empty())
return _InsertReturnType{end(), false, _NodeHandle()};
__node_pointer __ptr = __nh.__ptr_;
__parent_pointer __parent;
__node_base_pointer& __child = __find_equal(__parent,
__ptr->__value_);
if (__child != nullptr)
return _InsertReturnType{
iterator(static_cast<__node_pointer>(__child)),
false, _VSTD::move(__nh)};
__insert_node_at(__parent, __child,
static_cast<__node_base_pointer>(__ptr));
__nh.__release();
return _InsertReturnType{iterator(__ptr), true, _NodeHandle()};
}
template <class _Tp, class _Compare, class _Allocator>
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
typename __tree<_Tp, _Compare, _Allocator>::iterator
__tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(
const_iterator __hint, _NodeHandle&& __nh)
{
if (__nh.empty())
return end();
__node_pointer __ptr = __nh.__ptr_;
__parent_pointer __parent;
__node_base_pointer __dummy;
__node_base_pointer& __child = __find_equal(__hint, __parent, __dummy,
__ptr->__value_);
__node_pointer __r = static_cast<__node_pointer>(__child);
if (__child == nullptr)
{
__insert_node_at(__parent, __child,
static_cast<__node_base_pointer>(__ptr));
__r = __ptr;
__nh.__release();
}
return iterator(__r);
}
template <class _Tp, class _Compare, class _Allocator>
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
_NodeHandle
__tree<_Tp, _Compare, _Allocator>::__node_handle_extract(key_type const& __key)
{
iterator __it = find(__key);
if (__it == end())
return _NodeHandle();
return __node_handle_extract<_NodeHandle>(__it);
}
template <class _Tp, class _Compare, class _Allocator>
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
_NodeHandle
__tree<_Tp, _Compare, _Allocator>::__node_handle_extract(const_iterator __p)
{
__node_pointer __np = __p.__get_np();
__remove_node_pointer(__np);
return _NodeHandle(__np, __alloc());
}
template <class _Tp, class _Compare, class _Allocator>
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
typename __tree<_Tp, _Compare, _Allocator>::iterator
__tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(_NodeHandle&& __nh)
{
if (__nh.empty())
return end();
__node_pointer __ptr = __nh.__ptr_;
__parent_pointer __parent;
__node_base_pointer& __child = __find_leaf_high(
__parent, _NodeTypes::__get_key(__ptr->__value_));
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr));
__nh.__release();
return iterator(__ptr);
}
template <class _Tp, class _Compare, class _Allocator>
template <class _NodeHandle>
_LIBCPP_INLINE_VISIBILITY
typename __tree<_Tp, _Compare, _Allocator>::iterator
__tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(
const_iterator __hint, _NodeHandle&& __nh)
{
if (__nh.empty())
return end();
__node_pointer __ptr = __nh.__ptr_;
__parent_pointer __parent;
__node_base_pointer& __child = __find_leaf(__hint, __parent,
_NodeTypes::__get_key(__ptr->__value_));
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr));
__nh.__release();
return iterator(__ptr);
}
#endif // _LIBCPP_STD_VER > 14
template <class _Tp, class _Compare, class _Allocator>
typename __tree<_Tp, _Compare, _Allocator>::iterator
__tree<_Tp, _Compare, _Allocator>::erase(const_iterator __p)
{
__node_pointer __np = __p.__get_np();
iterator __r(__p.__ptr_);
++__r;
if (__begin_node() == __p.__ptr_)
__begin_node() = __r.__ptr_;
--size();
iterator __r = __remove_node_pointer(__np);
__node_allocator& __na = __node_alloc();
__tree_remove(__end_node()->__left_,
static_cast<__node_base_pointer>(__np));
__node_traits::destroy(__na, _NodeTypes::__get_ptr(
const_cast<__node_value_type&>(*__p)));
__node_traits::deallocate(__na, __np, 1);

View File

@ -40,6 +40,8 @@ public:
typedef implementation-defined const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef unspecified node_type; // C++17
typedef INSERT_RETURN_TYPE<iterator, node_type> insert_return_type; // C++17
class value_compare
: public binary_function<value_type, value_type, bool>
@ -137,6 +139,11 @@ public:
void insert(InputIterator first, InputIterator last);
void insert(initializer_list<value_type> il);
node_type extract(const_iterator position); // C++17
node_type extract(const key_type& x); // C++17
insert_return_type insert(node_type&& nh); // C++17
iterator insert(const_iterator hint, node_type&& nh); // C++17
template <class... Args>
pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); // C++17
template <class... Args>
@ -260,6 +267,7 @@ public:
typedef implementation-defined const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef unspecified node_type; // C++17
class value_compare
: public binary_function<value_type,value_type,bool>
@ -349,6 +357,11 @@ public:
void insert(InputIterator first, InputIterator last);
void insert(initializer_list<value_type> il);
node_type extract(const_iterator position); // C++17
node_type extract(const key_type& x); // C++17
iterator insert(node_type&& nh); // C++17
iterator insert(const_iterator hint, node_type&& nh); // C++17
iterator erase(const_iterator position);
iterator erase(iterator position); // C++14
size_type erase(const key_type& k);
@ -440,6 +453,7 @@ swap(multimap<Key, T, Compare, Allocator>& x,
#include <__config>
#include <__tree>
#include <__node_handle>
#include <iterator>
#include <memory>
#include <utility>
@ -906,6 +920,11 @@ public:
typedef _VSTD::reverse_iterator<iterator> reverse_iterator;
typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator;
#if _LIBCPP_STD_VER > 14
typedef __map_node_handle<typename __base::__node, allocator_type> node_type;
typedef __insert_return_type<iterator, node_type> insert_return_type;
#endif
_LIBCPP_INLINE_VISIBILITY
map()
_NOEXCEPT_(
@ -1253,6 +1272,35 @@ public:
_LIBCPP_INLINE_VISIBILITY
void clear() _NOEXCEPT {__tree_.clear();}
#if _LIBCPP_STD_VER > 14
_LIBCPP_INLINE_VISIBILITY
insert_return_type insert(node_type&& __nh)
{
_LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(),
"node_type with incompatible allocator passed to map::insert()");
return __tree_.template __node_handle_insert_unique<
node_type, insert_return_type>(_VSTD::move(__nh));
}
_LIBCPP_INLINE_VISIBILITY
iterator insert(const_iterator __hint, node_type&& __nh)
{
_LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(),
"node_type with incompatible allocator passed to map::insert()");
return __tree_.template __node_handle_insert_unique<node_type>(
__hint.__i_, _VSTD::move(__nh));
}
_LIBCPP_INLINE_VISIBILITY
node_type extract(key_type const& __key)
{
return __tree_.template __node_handle_extract<node_type>(__key);
}
_LIBCPP_INLINE_VISIBILITY
node_type extract(const_iterator __it)
{
return __tree_.template __node_handle_extract<node_type>(__it.__i_);
}
#endif
_LIBCPP_INLINE_VISIBILITY
void swap(map& __m)
_NOEXCEPT_(__is_nothrow_swappable<__base>::value)
@ -1562,6 +1610,10 @@ public:
typedef _VSTD::reverse_iterator<iterator> reverse_iterator;
typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator;
#if _LIBCPP_STD_VER > 14
typedef __map_node_handle<typename __base::__node, allocator_type> node_type;
#endif
_LIBCPP_INLINE_VISIBILITY
multimap()
_NOEXCEPT_(
@ -1800,6 +1852,37 @@ public:
_LIBCPP_INLINE_VISIBILITY
iterator erase(const_iterator __f, const_iterator __l)
{return __tree_.erase(__f.__i_, __l.__i_);}
#if _LIBCPP_STD_VER > 14
_LIBCPP_INLINE_VISIBILITY
iterator insert(node_type&& __nh)
{
_LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(),
"node_type with incompatible allocator passed to multimap::insert()");
return __tree_.template __node_handle_insert_multi<node_type>(
_VSTD::move(__nh));
}
_LIBCPP_INLINE_VISIBILITY
iterator insert(const_iterator __hint, node_type&& __nh)
{
_LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(),
"node_type with incompatible allocator passed to multimap::insert()");
return __tree_.template __node_handle_insert_multi<node_type>(
__hint.__i_, _VSTD::move(__nh));
}
_LIBCPP_INLINE_VISIBILITY
node_type extract(key_type const& __key)
{
return __tree_.template __node_handle_extract<node_type>(__key);
}
_LIBCPP_INLINE_VISIBILITY
node_type extract(const_iterator __it)
{
return __tree_.template __node_handle_extract<node_type>(
__it.__i_);
}
#endif
_LIBCPP_INLINE_VISIBILITY
void clear() {__tree_.clear();}

View File

@ -498,6 +498,7 @@ module std [system] {
module __tree { header "__tree" export * }
module __tuple { header "__tuple" export * }
module __undef_macros { header "__undef_macros" export * }
module __node_handle { header "__node_handle" export * }
module experimental {
requires cplusplus11

View File

@ -40,6 +40,8 @@ public:
typedef implementation-defined const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef unspecified node_type; // C++17
typedef INSERT_RETURN_TYPE<iterator, node_type> insert_return_type; // C++17
// construct/copy/destroy:
set()
@ -115,6 +117,11 @@ public:
void insert(InputIterator first, InputIterator last);
void insert(initializer_list<value_type> il);
node_type extract(const_iterator position); // C++17
node_type extract(const key_type& x); // C++17
insert_return_type insert(node_type&& nh); // C++17
iterator insert(const_iterator hint, node_type&& nh); // C++17
iterator erase(const_iterator position);
iterator erase(iterator position); // C++14
size_type erase(const key_type& k);
@ -222,6 +229,7 @@ public:
typedef implementation-defined const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef unspecified node_type; // C++17
// construct/copy/destroy:
multiset()
@ -297,6 +305,11 @@ public:
void insert(InputIterator first, InputIterator last);
void insert(initializer_list<value_type> il);
node_type extract(const_iterator position); // C++17
node_type extract(const key_type& x); // C++17
iterator insert(node_type&& nh); // C++17
iterator insert(const_iterator hint, node_type&& nh); // C++17
iterator erase(const_iterator position);
iterator erase(iterator position); // C++14
size_type erase(const key_type& k);
@ -387,6 +400,7 @@ swap(multiset<Key, Compare, Allocator>& x, multiset<Key, Compare, Allocator>& y)
#include <__config>
#include <__tree>
#include <__node_handle>
#include <functional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@ -429,6 +443,11 @@ public:
typedef _VSTD::reverse_iterator<iterator> reverse_iterator;
typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator;
#if _LIBCPP_STD_VER > 14
typedef __set_node_handle<typename __base::__node, allocator_type> node_type;
typedef __insert_return_type<iterator, node_type> insert_return_type;
#endif
_LIBCPP_INLINE_VISIBILITY
set()
_NOEXCEPT_(
@ -634,6 +653,35 @@ public:
_LIBCPP_INLINE_VISIBILITY
void clear() _NOEXCEPT {__tree_.clear();}
#if _LIBCPP_STD_VER > 14
_LIBCPP_INLINE_VISIBILITY
insert_return_type insert(node_type&& __nh)
{
_LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(),
"node_type with incompatible allocator passed to set::insert()");
return __tree_.template __node_handle_insert_unique<
node_type, insert_return_type>(_VSTD::move(__nh));
}
_LIBCPP_INLINE_VISIBILITY
iterator insert(const_iterator __hint, node_type&& __nh)
{
_LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(),
"node_type with incompatible allocator passed to set::insert()");
return __tree_.template __node_handle_insert_unique<node_type>(
__hint, _VSTD::move(__nh));
}
_LIBCPP_INLINE_VISIBILITY
node_type extract(key_type const& __key)
{
return __tree_.template __node_handle_extract<node_type>(__key);
}
_LIBCPP_INLINE_VISIBILITY
node_type extract(const_iterator __it)
{
return __tree_.template __node_handle_extract<node_type>(__it);
}
#endif
_LIBCPP_INLINE_VISIBILITY
void swap(set& __s) _NOEXCEPT_(__is_nothrow_swappable<__base>::value)
{__tree_.swap(__s.__tree_);}
@ -838,6 +886,10 @@ public:
typedef _VSTD::reverse_iterator<iterator> reverse_iterator;
typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator;
#if _LIBCPP_STD_VER > 14
typedef __set_node_handle<typename __base::__node, allocator_type> node_type;
#endif
// construct/copy/destroy:
_LIBCPP_INLINE_VISIBILITY
multiset()
@ -1042,6 +1094,35 @@ public:
_LIBCPP_INLINE_VISIBILITY
void clear() _NOEXCEPT {__tree_.clear();}
#if _LIBCPP_STD_VER > 14
_LIBCPP_INLINE_VISIBILITY
iterator insert(node_type&& __nh)
{
_LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(),
"node_type with incompatible allocator passed to multiset::insert()");
return __tree_.template __node_handle_insert_multi<node_type>(
_VSTD::move(__nh));
}
_LIBCPP_INLINE_VISIBILITY
iterator insert(const_iterator __hint, node_type&& __nh)
{
_LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(),
"node_type with incompatible allocator passed to multiset::insert()");
return __tree_.template __node_handle_insert_multi<node_type>(
__hint, _VSTD::move(__nh));
}
_LIBCPP_INLINE_VISIBILITY
node_type extract(key_type const& __key)
{
return __tree_.template __node_handle_extract<node_type>(__key);
}
_LIBCPP_INLINE_VISIBILITY
node_type extract(const_iterator __it)
{
return __tree_.template __node_handle_extract<node_type>(__it);
}
#endif
_LIBCPP_INLINE_VISIBILITY
void swap(multiset& __s)
_NOEXCEPT_(__is_nothrow_swappable<__base>::value)

View File

@ -44,6 +44,9 @@ public:
typedef /unspecified/ local_iterator;
typedef /unspecified/ const_local_iterator;
typedef unspecified node_type; // C++17
typedef INSERT_RETURN_TYPE<iterator, node_type> insert_return_type; // C++17
unordered_map()
noexcept(
is_nothrow_default_constructible<hasher>::value &&
@ -122,6 +125,11 @@ public:
void insert(InputIterator first, InputIterator last);
void insert(initializer_list<value_type>);
node_type extract(const_iterator position); // C++17
node_type extract(const key_type& x); // C++17
insert_return_type insert(node_type&& nh); // C++17
iterator insert(const_iterator hint, node_type&& nh); // C++17
template <class... Args>
pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); // C++17
template <class... Args>
@ -226,6 +234,8 @@ public:
typedef /unspecified/ local_iterator;
typedef /unspecified/ const_local_iterator;
typedef unspecified node_type; // C++17
unordered_multimap()
noexcept(
is_nothrow_default_constructible<hasher>::value &&
@ -304,6 +314,11 @@ public:
void insert(InputIterator first, InputIterator last);
void insert(initializer_list<value_type>);
node_type extract(const_iterator position); // C++17
node_type extract(const key_type& x); // C++17
iterator insert(node_type&& nh); // C++17
iterator insert(const_iterator hint, node_type&& nh); // C++17
iterator erase(const_iterator position);
iterator erase(iterator position); // C++14
size_type erase(const key_type& k);
@ -367,6 +382,7 @@ template <class Key, class T, class Hash, class Pred, class Alloc>
#include <__config>
#include <__hash_table>
#include <__node_handle>
#include <functional>
#include <stdexcept>
#include <tuple>
@ -843,6 +859,11 @@ public:
typedef __hash_map_iterator<typename __table::local_iterator> local_iterator;
typedef __hash_map_const_iterator<typename __table::const_local_iterator> const_local_iterator;
#if _LIBCPP_STD_VER > 14
typedef __map_node_handle<__node, allocator_type> node_type;
typedef __insert_return_type<iterator, node_type> insert_return_type;
#endif
_LIBCPP_INLINE_VISIBILITY
unordered_map()
_NOEXCEPT_(is_nothrow_default_constructible<__table>::value)
@ -1136,7 +1157,37 @@ public:
iterator erase(const_iterator __first, const_iterator __last)
{return __table_.erase(__first.__i_, __last.__i_);}
_LIBCPP_INLINE_VISIBILITY
void clear() _NOEXCEPT {__table_.clear();}
void clear() _NOEXCEPT {__table_.clear();}
#if _LIBCPP_STD_VER > 14
_LIBCPP_INLINE_VISIBILITY
insert_return_type insert(node_type&& __nh)
{
_LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(),
"node_type with incompatible allocator passed to unordered_map::insert()");
return __table_.template __node_handle_insert_unique<
node_type, insert_return_type>(_VSTD::move(__nh));
}
_LIBCPP_INLINE_VISIBILITY
iterator insert(const_iterator __hint, node_type&& __nh)
{
_LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(),
"node_type with incompatible allocator passed to unordered_map::insert()");
return __table_.template __node_handle_insert_unique<node_type>(
__hint.__i_, _VSTD::move(__nh));
}
_LIBCPP_INLINE_VISIBILITY
node_type extract(key_type const& __key)
{
return __table_.template __node_handle_extract<node_type>(__key);
}
_LIBCPP_INLINE_VISIBILITY
node_type extract(const_iterator __it)
{
return __table_.template __node_handle_extract<node_type>(
__it.__i_);
}
#endif
_LIBCPP_INLINE_VISIBILITY
void swap(unordered_map& __u)
@ -1590,6 +1641,10 @@ public:
typedef __hash_map_iterator<typename __table::local_iterator> local_iterator;
typedef __hash_map_const_iterator<typename __table::const_local_iterator> const_local_iterator;
#if _LIBCPP_STD_VER > 14
typedef __map_node_handle<__node, allocator_type> node_type;
#endif
_LIBCPP_INLINE_VISIBILITY
unordered_multimap()
_NOEXCEPT_(is_nothrow_default_constructible<__table>::value)
@ -1763,6 +1818,36 @@ public:
_LIBCPP_INLINE_VISIBILITY
void clear() _NOEXCEPT {__table_.clear();}
#if _LIBCPP_STD_VER > 14
_LIBCPP_INLINE_VISIBILITY
iterator insert(node_type&& __nh)
{
_LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(),
"node_type with incompatible allocator passed to unordered_multimap::insert()");
return __table_.template __node_handle_insert_multi<node_type>(
_VSTD::move(__nh));
}
_LIBCPP_INLINE_VISIBILITY
iterator insert(const_iterator __hint, node_type&& __nh)
{
_LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(),
"node_type with incompatible allocator passed to unordered_multimap::insert()");
return __table_.template __node_handle_insert_multi<node_type>(
__hint.__i_, _VSTD::move(__nh));
}
_LIBCPP_INLINE_VISIBILITY
node_type extract(key_type const& __key)
{
return __table_.template __node_handle_extract<node_type>(__key);
}
_LIBCPP_INLINE_VISIBILITY
node_type extract(const_iterator __it)
{
return __table_.template __node_handle_extract<node_type>(
__it.__i_);
}
#endif
_LIBCPP_INLINE_VISIBILITY
void swap(unordered_multimap& __u)
_NOEXCEPT_(__is_nothrow_swappable<__table>::value)

View File

@ -43,6 +43,9 @@ public:
typedef /unspecified/ local_iterator;
typedef /unspecified/ const_local_iterator;
typedef unspecified node_type unspecified; // C++17
typedef INSERT_RETURN_TYPE<iterator, node_type> insert_return_type; // C++17
unordered_set()
noexcept(
is_nothrow_default_constructible<hasher>::value &&
@ -113,6 +116,11 @@ public:
void insert(InputIterator first, InputIterator last);
void insert(initializer_list<value_type>);
node_type extract(const_iterator position); // C++17
node_type extract(const key_type& x); // C++17
insert_return_type insert(node_type&& nh); // C++17
iterator insert(const_iterator hint, node_type&& nh); // C++17
iterator erase(const_iterator position);
iterator erase(iterator position); // C++14
size_type erase(const key_type& k);
@ -191,6 +199,8 @@ public:
typedef /unspecified/ local_iterator;
typedef /unspecified/ const_local_iterator;
typedef unspecified node_type unspecified; // C++17
unordered_multiset()
noexcept(
is_nothrow_default_constructible<hasher>::value &&
@ -261,6 +271,11 @@ public:
void insert(InputIterator first, InputIterator last);
void insert(initializer_list<value_type>);
node_type extract(const_iterator position); // C++17
node_type extract(const key_type& x); // C++17
iterator insert(node_type&& nh); // C++17
iterator insert(const_iterator hint, node_type&& nh); // C++17
iterator erase(const_iterator position);
iterator erase(iterator position); // C++14
size_type erase(const key_type& k);
@ -321,6 +336,7 @@ template <class Value, class Hash, class Pred, class Alloc>
#include <__config>
#include <__hash_table>
#include <__node_handle>
#include <functional>
#include <__debug>
@ -363,6 +379,11 @@ public:
typedef typename __table::const_local_iterator local_iterator;
typedef typename __table::const_local_iterator const_local_iterator;
#if _LIBCPP_STD_VER > 14
typedef __set_node_handle<typename __table::__node, allocator_type> node_type;
typedef __insert_return_type<iterator, node_type> insert_return_type;
#endif
_LIBCPP_INLINE_VISIBILITY
unordered_set()
_NOEXCEPT_(is_nothrow_default_constructible<__table>::value)
@ -541,6 +562,35 @@ public:
_LIBCPP_INLINE_VISIBILITY
void clear() _NOEXCEPT {__table_.clear();}
#if _LIBCPP_STD_VER > 14
_LIBCPP_INLINE_VISIBILITY
insert_return_type insert(node_type&& __nh)
{
_LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(),
"node_type with incompatible allocator passed to unordered_set::insert()");
return __table_.template __node_handle_insert_unique<
node_type, insert_return_type>(_VSTD::move(__nh));
}
_LIBCPP_INLINE_VISIBILITY
iterator insert(const_iterator __h, node_type&& __nh)
{
_LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(),
"node_type with incompatible allocator passed to unordered_set::insert()");
return __table_.template __node_handle_insert_unique<node_type>(
__h, _VSTD::move(__nh));
}
_LIBCPP_INLINE_VISIBILITY
node_type extract(key_type const& __key)
{
return __table_.template __node_handle_extract<node_type>(__key);
}
_LIBCPP_INLINE_VISIBILITY
node_type extract(const_iterator __it)
{
return __table_.template __node_handle_extract<node_type>(__it);
}
#endif
_LIBCPP_INLINE_VISIBILITY
void swap(unordered_set& __u)
_NOEXCEPT_(__is_nothrow_swappable<__table>::value)
@ -883,6 +933,10 @@ public:
typedef typename __table::const_local_iterator local_iterator;
typedef typename __table::const_local_iterator const_local_iterator;
#if _LIBCPP_STD_VER > 14
typedef __set_node_handle<typename __table::__node, allocator_type> node_type;
#endif
_LIBCPP_INLINE_VISIBILITY
unordered_multiset()
_NOEXCEPT_(is_nothrow_default_constructible<__table>::value)
@ -1019,6 +1073,36 @@ public:
_LIBCPP_INLINE_VISIBILITY
void insert(_InputIterator __first, _InputIterator __last);
#if _LIBCPP_STD_VER > 14
_LIBCPP_INLINE_VISIBILITY
iterator insert(node_type&& __nh)
{
_LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(),
"node_type with incompatible allocator passed to unordered_multiset::insert()");
return __table_.template __node_handle_insert_multi<node_type>(
_VSTD::move(__nh));
}
_LIBCPP_INLINE_VISIBILITY
iterator insert(const_iterator __hint, node_type&& __nh)
{
_LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(),
"node_type with incompatible allocator passed to unordered_multiset::insert()");
return __table_.template __node_handle_insert_multi<node_type>(
__hint, _VSTD::move(__nh));
}
_LIBCPP_INLINE_VISIBILITY
node_type extract(const_iterator __position)
{
return __table_.template __node_handle_extract<node_type>(
__position);
}
_LIBCPP_INLINE_VISIBILITY
node_type extract(key_type const& __key)
{
return __table_.template __node_handle_extract<node_type>(__key);
}
#endif
_LIBCPP_INLINE_VISIBILITY
iterator erase(const_iterator __p) {return __table_.erase(__p);}
_LIBCPP_INLINE_VISIBILITY

View File

@ -0,0 +1,67 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <map>
// class map
// node_type extract(const_iterator);
#include <map>
#include "min_allocator.h"
#include "Counter.h"
template <class Container>
void test(Container& c)
{
size_t sz = c.size();
auto some_key = c.cbegin()->first;
for (auto first = c.cbegin(); first != c.cend();)
{
auto key_value = first->first;
typename Container::node_type t = c.extract(first++);
--sz;
assert(t.key() == key_value);
t.key() = some_key;
assert(t.key() == some_key);
assert(t.get_allocator() == c.get_allocator());
assert(sz == c.size());
}
assert(c.size() == 0);
}
int main()
{
{
using map_type = std::map<int, int>;
map_type m = {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}};
test(m);
}
{
std::map<Counter<int>, Counter<int>> m =
{{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}};
assert(Counter_base::gConstructed == 12);
test(m);
assert(Counter_base::gConstructed == 0);
}
{
using min_alloc_map =
std::map<int, int, std::less<int>,
min_allocator<std::pair<const int, int>>>;
min_alloc_map m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}};
test(m);
}
}

View File

@ -0,0 +1,76 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <map>
// class map
// node_type extract(key_type const&);
#include <map>
#include "min_allocator.h"
#include "Counter.h"
template <class Container, class KeyTypeIter>
void test(Container& c, KeyTypeIter first, KeyTypeIter last)
{
size_t sz = c.size();
assert((size_t)std::distance(first, last) == sz);
for (KeyTypeIter copy = first; copy != last; ++copy)
{
typename Container::node_type t = c.extract(*copy);
assert(!t.empty());
--sz;
assert(t.key() == *copy);
t.key() = *first; // We should be able to mutate key.
assert(t.key() == *first);
assert(t.get_allocator() == c.get_allocator());
assert(sz == c.size());
}
assert(c.size() == 0);
for (KeyTypeIter copy = first; copy != last; ++copy)
{
typename Container::node_type t = c.extract(*copy);
assert(t.empty());
}
}
int main()
{
{
std::map<int, int> m = {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}};
int keys[] = {1, 2, 3, 4, 5, 6};
test(m, std::begin(keys), std::end(keys));
}
{
std::map<Counter<int>, Counter<int>> m =
{{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}};
{
Counter<int> keys[] = {1, 2, 3, 4, 5, 6};
assert(Counter_base::gConstructed == 12+6);
test(m, std::begin(keys), std::end(keys));
}
assert(Counter_base::gConstructed == 0);
}
{
using min_alloc_map =
std::map<int, int, std::less<int>,
min_allocator<std::pair<const int, int>>>;
min_alloc_map m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}};
int keys[] = {1, 2, 3, 4, 5, 6};
test(m, std::begin(keys), std::end(keys));
}
}

View File

@ -0,0 +1,85 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <map>
// class map
// insert_return_type insert(node_type&&);
#include <map>
#include <type_traits>
#include "min_allocator.h"
template <class Container>
typename Container::node_type
node_factory(typename Container::key_type const& key,
typename Container::mapped_type const& mapped)
{
static Container c;
auto p = c.insert({key, mapped});
assert(p.second);
return c.extract(p.first);
}
template <class Container>
void test(Container& c)
{
auto* nf = &node_factory<Container>;
for (int i = 0; i != 10; ++i)
{
typename Container::node_type node = nf(i, i + 1);
assert(!node.empty());
typename Container::insert_return_type irt = c.insert(std::move(node));
assert(node.empty());
assert(irt.inserted);
assert(irt.node.empty());
assert(irt.position->first == i && irt.position->second == i + 1);
}
assert(c.size() == 10);
{ // Insert empty node.
typename Container::node_type def;
auto irt = c.insert(std::move(def));
assert(def.empty());
assert(!irt.inserted);
assert(irt.node.empty());
assert(irt.position == c.end());
}
{ // Insert duplicate node.
typename Container::node_type dupl = nf(0, 42);
auto irt = c.insert(std::move(dupl));
assert(dupl.empty());
assert(!irt.inserted);
assert(!irt.node.empty());
assert(irt.position == c.find(0));
assert(irt.node.key() == 0 && irt.node.mapped() == 42);
}
assert(c.size() == 10);
for (int i = 0; i != 10; ++i)
{
assert(c.count(i) == 1);
assert(c[i] == i + 1);
}
}
int main()
{
std::map<int, int> m;
test(m);
std::map<int, int, std::less<int>, min_allocator<std::pair<const int, int>>> m2;
test(m2);
}

View File

@ -0,0 +1,64 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <map>
// class map
// iterator insert(const_iterator hint, node_type&&);
#include <map>
#include "min_allocator.h"
template <class Container>
typename Container::node_type
node_factory(typename Container::key_type const& key,
typename Container::mapped_type const& mapped)
{
static Container c;
auto p = c.insert({key, mapped});
assert(p.second);
return c.extract(p.first);
}
template <class Container>
void test(Container& c)
{
auto* nf = &node_factory<Container>;
for (int i = 0; i != 10; ++i)
{
typename Container::node_type node = nf(i, i + 1);
assert(!node.empty());
size_t prev = c.size();
auto it = c.insert(c.end(), std::move(node));
assert(node.empty());
assert(prev + 1 == c.size());
assert(it->first == i);
assert(it->second == i + 1);
}
assert(c.size() == 10);
for (int i = 0; i != 10; ++i)
{
assert(c.count(i) == 1);
assert(c[i] == i + 1);
}
}
int main()
{
std::map<int, int> m;
test(m);
std::map<int, int, std::less<int>, min_allocator<std::pair<const int, int>>> m2;
test(m2);
}

View File

@ -0,0 +1,67 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <map>
// class multimap
// node_type extract(const_iterator);
#include <map>
#include "min_allocator.h"
#include "Counter.h"
template <class Container>
void test(Container& c)
{
size_t sz = c.size();
auto some_key = c.cbegin()->first;
for (auto first = c.cbegin(); first != c.cend();)
{
auto key_value = first->first;
typename Container::node_type t = c.extract(first++);
--sz;
assert(t.key() == key_value);
t.key() = some_key;
assert(t.key() == some_key);
assert(t.get_allocator() == c.get_allocator());
assert(sz == c.size());
}
assert(c.size() == 0);
}
int main()
{
{
using map_type = std::multimap<int, int>;
map_type m = {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}};
test(m);
}
{
std::multimap<Counter<int>, Counter<int>> m =
{{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}};
assert(Counter_base::gConstructed == 12);
test(m);
assert(Counter_base::gConstructed == 0);
}
{
using min_alloc_map =
std::multimap<int, int, std::less<int>,
min_allocator<std::pair<const int, int>>>;
min_alloc_map m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}};
test(m);
}
}

View File

@ -0,0 +1,76 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <map>
// class multimap
// node_type extract(key_type const&);
#include <map>
#include "min_allocator.h"
#include "Counter.h"
template <class Container, class KeyTypeIter>
void test(Container& c, KeyTypeIter first, KeyTypeIter last)
{
size_t sz = c.size();
assert((size_t)std::distance(first, last) == sz);
for (KeyTypeIter copy = first; copy != last; ++copy)
{
typename Container::node_type t = c.extract(*copy);
assert(!t.empty());
--sz;
assert(t.key() == *copy);
t.key() = *first; // We should be able to mutate key.
assert(t.key() == *first);
assert(t.get_allocator() == c.get_allocator());
assert(sz == c.size());
}
assert(c.size() == 0);
for (KeyTypeIter copy = first; copy != last; ++copy)
{
typename Container::node_type t = c.extract(*copy);
assert(t.empty());
}
}
int main()
{
{
std::multimap<int, int> m = {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}};
int keys[] = {1, 2, 3, 4, 5, 6};
test(m, std::begin(keys), std::end(keys));
}
{
std::multimap<Counter<int>, Counter<int>> m =
{{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}};
{
Counter<int> keys[] = {1, 2, 3, 4, 5, 6};
assert(Counter_base::gConstructed == 12+6);
test(m, std::begin(keys), std::end(keys));
}
assert(Counter_base::gConstructed == 0);
}
{
using min_alloc_map =
std::multimap<int, int, std::less<int>,
min_allocator<std::pair<const int, int>>>;
min_alloc_map m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}};
int keys[] = {1, 2, 3, 4, 5, 6};
test(m, std::begin(keys), std::end(keys));
}
}

View File

@ -0,0 +1,78 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <map>
// class multimap
// iterator insert(node_type&&);
#include <map>
#include <type_traits>
#include "min_allocator.h"
template <class Container>
typename Container::node_type
node_factory(typename Container::key_type const& key,
typename Container::mapped_type const& mapped)
{
static Container c;
auto it = c.insert({key, mapped});
return c.extract(it);
}
template <class Container>
void test(Container& c)
{
auto* nf = &node_factory<Container>;
for (int i = 0; i != 10; ++i)
{
typename Container::node_type node = nf(i, i + 1);
assert(!node.empty());
typename Container::iterator it = c.insert(std::move(node));
assert(node.empty());
assert(it == c.find(i) && it != c.end());
}
assert(c.size() == 10);
{ // Insert empty node.
typename Container::node_type def;
auto it = c.insert(std::move(def));
assert(def.empty());
assert(it == c.end());
}
{ // Insert duplicate node.
typename Container::node_type dupl = nf(0, 42);
auto it = c.insert(std::move(dupl));
assert(dupl.empty());
assert(it != c.end());
assert(it->second == 42);
}
assert(c.size() == 11);
assert(c.count(0) == 2);
for (int i = 1; i != 10; ++i)
{
assert(c.count(i) == 1);
assert(c.find(i)->second == i + 1);
}
}
int main()
{
std::multimap<int, int> m;
test(m);
std::multimap<int, int, std::less<int>, min_allocator<std::pair<const int, int>>> m2;
test(m2);
}

View File

@ -0,0 +1,64 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <map>
// class multimap
// iterator insert(const_iterator hint, node_type&&);
#include <map>
#include "min_allocator.h"
template <class Container>
typename Container::node_type
node_factory(typename Container::key_type const& key,
typename Container::mapped_type const& mapped)
{
static Container c;
auto it = c.insert({key, mapped});
return c.extract(it);
}
template <class Container>
void test(Container& c)
{
auto* nf = &node_factory<Container>;
for (int i = 0; i != 10; ++i)
{
typename Container::node_type node = nf(i, i + 1);
assert(!node.empty());
size_t prev = c.size();
auto it = c.insert(c.end(), std::move(node));
assert(node.empty());
assert(prev + 1 == c.size());
assert(it == c.find(i));
assert(it->first == i);
assert(it->second == i + 1);
}
assert(c.size() == 10);
for (int i = 0; i != 10; ++i)
{
assert(c.count(i) == 1);
assert(c.find(i)->second == i + 1);
}
}
int main()
{
std::multimap<int, int> m;
test(m);
std::multimap<int, int, std::less<int>, min_allocator<std::pair<const int, int>>> m2;
test(m2);
}

View File

@ -0,0 +1,60 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <set>
// class multiset
// node_type extract(const_iterator);
#include <set>
#include "min_allocator.h"
#include "Counter.h"
template <class Container>
void test(Container& c)
{
size_t sz = c.size();
for (auto first = c.cbegin(); first != c.cend();)
{
auto key_value = *first;
typename Container::node_type t = c.extract(first++);
--sz;
assert(t.value() == key_value);
assert(t.get_allocator() == c.get_allocator());
assert(sz == c.size());
}
assert(c.size() == 0);
}
int main()
{
{
using set_type = std::multiset<int>;
set_type m = {1, 2, 3, 4, 5, 6};
test(m);
}
{
std::multiset<Counter<int>> m = {1, 2, 3, 4, 5, 6};
assert(Counter_base::gConstructed == 6);
test(m);
assert(Counter_base::gConstructed == 0);
}
{
using min_alloc_set = std::multiset<int, std::less<int>, min_allocator<int>>;
min_alloc_set m = {1, 2, 3, 4, 5, 6};
test(m);
}
}

View File

@ -0,0 +1,71 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <set>
// class multiset
// node_type extract(key_type const&);
#include <set>
#include "min_allocator.h"
#include "Counter.h"
template <class Container, class KeyTypeIter>
void test(Container& c, KeyTypeIter first, KeyTypeIter last)
{
size_t sz = c.size();
assert((size_t)std::distance(first, last) == sz);
for (KeyTypeIter copy = first; copy != last; ++copy)
{
typename Container::node_type t = c.extract(*copy);
assert(!t.empty());
--sz;
assert(t.value() == *copy);
assert(t.get_allocator() == c.get_allocator());
assert(sz == c.size());
}
assert(c.size() == 0);
for (KeyTypeIter copy = first; copy != last; ++copy)
{
typename Container::node_type t = c.extract(*copy);
assert(t.empty());
}
}
int main()
{
{
std::multiset<int> m = {1, 2, 3, 4, 5, 6};
int keys[] = {1, 2, 3, 4, 5, 6};
test(m, std::begin(keys), std::end(keys));
}
{
std::multiset<Counter<int>> m = {1, 2, 3, 4, 5, 6};
{
Counter<int> keys[] = {1, 2, 3, 4, 5, 6};
assert(Counter_base::gConstructed == 6+6);
test(m, std::begin(keys), std::end(keys));
}
assert(Counter_base::gConstructed == 0);
}
{
using min_alloc_set = std::multiset<int, std::less<int>, min_allocator<int>>;
min_alloc_set m = {1, 2, 3, 4, 5, 6};
int keys[] = {1, 2, 3, 4, 5, 6};
test(m, std::begin(keys), std::end(keys));
}
}

View File

@ -0,0 +1,77 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <set>
// class multiset
// iterator insert(node_type&&);
#include <set>
#include <type_traits>
#include "min_allocator.h"
template <class Container>
typename Container::node_type
node_factory(typename Container::key_type const& key)
{
static Container c;
auto it = c.insert(key);
return c.extract(it);
}
template <class Container>
void test(Container& c)
{
auto* nf = &node_factory<Container>;
for (int i = 0; i != 10; ++i)
{
typename Container::node_type node = nf(i);
assert(!node.empty());
typename Container::iterator it = c.insert(std::move(node));
assert(node.empty());
assert(it == c.find(i) && it != c.end());
assert(*it == i);
assert(node.empty());
}
assert(c.size() == 10);
{ // Insert empty node.
typename Container::node_type def;
auto it = c.insert(std::move(def));
assert(def.empty());
assert(it == c.end());
}
{ // Insert duplicate node.
typename Container::node_type dupl = nf(0);
auto it = c.insert(std::move(dupl));
assert(*it == 0);
}
assert(c.size() == 11);
assert(c.count(0) == 2);
for (int i = 1; i != 10; ++i)
{
assert(c.count(i) == 1);
}
}
int main()
{
std::multiset<int> m;
test(m);
std::multiset<int, std::less<int>, min_allocator<int>> m2;
test(m2);
}

View File

@ -0,0 +1,59 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <set>
// class multiset
// iterator insert(const_iterator hint, node_type&&);
#include <set>
#include "min_allocator.h"
template <class Container>
typename Container::node_type
node_factory(typename Container::key_type const& key)
{
static Container c;
auto it = c.insert(key);
return c.extract(it);
}
template <class Container>
void test(Container& c)
{
auto* nf = &node_factory<Container>;
for (int i = 0; i != 10; ++i)
{
typename Container::node_type node = nf(i);
assert(!node.empty());
size_t prev = c.size();
auto it = c.insert(c.end(), std::move(node));
assert(prev + 1 == c.size());
assert(*it == i);
}
assert(c.size() == 10);
for (int i = 0; i != 10; ++i)
{
assert(c.count(i) == 1);
}
}
int main()
{
std::multiset<int> m;
test(m);
std::multiset<int, std::less<int>, min_allocator<int>> m2;
test(m2);
}

View File

@ -0,0 +1,60 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <set>
// class set
// node_type extract(const_iterator);
#include <set>
#include "min_allocator.h"
#include "Counter.h"
template <class Container>
void test(Container& c)
{
size_t sz = c.size();
for (auto first = c.cbegin(); first != c.cend();)
{
auto key_value = *first;
typename Container::node_type t = c.extract(first++);
--sz;
assert(t.value() == key_value);
assert(t.get_allocator() == c.get_allocator());
assert(sz == c.size());
}
assert(c.size() == 0);
}
int main()
{
{
using set_type = std::set<int>;
set_type m = {1, 2, 3, 4, 5, 6};
test(m);
}
{
std::set<Counter<int>> m = {1, 2, 3, 4, 5, 6};
assert(Counter_base::gConstructed == 6);
test(m);
assert(Counter_base::gConstructed == 0);
}
{
using min_alloc_set = std::set<int, std::less<int>, min_allocator<int>>;
min_alloc_set m = {1, 2, 3, 4, 5, 6};
test(m);
}
}

View File

@ -0,0 +1,71 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <set>
// class set
// node_type extract(key_type const&);
#include <set>
#include "min_allocator.h"
#include "Counter.h"
template <class Container, class KeyTypeIter>
void test(Container& c, KeyTypeIter first, KeyTypeIter last)
{
size_t sz = c.size();
assert((size_t)std::distance(first, last) == sz);
for (KeyTypeIter copy = first; copy != last; ++copy)
{
typename Container::node_type t = c.extract(*copy);
assert(!t.empty());
--sz;
assert(t.value() == *copy);
assert(t.get_allocator() == c.get_allocator());
assert(sz == c.size());
}
assert(c.size() == 0);
for (KeyTypeIter copy = first; copy != last; ++copy)
{
typename Container::node_type t = c.extract(*copy);
assert(t.empty());
}
}
int main()
{
{
std::set<int> m = {1, 2, 3, 4, 5, 6};
int keys[] = {1, 2, 3, 4, 5, 6};
test(m, std::begin(keys), std::end(keys));
}
{
std::set<Counter<int>> m = {1, 2, 3, 4, 5, 6};
{
Counter<int> keys[] = {1, 2, 3, 4, 5, 6};
assert(Counter_base::gConstructed == 6+6);
test(m, std::begin(keys), std::end(keys));
}
assert(Counter_base::gConstructed == 0);
}
{
using min_alloc_set = std::set<int, std::less<int>, min_allocator<int>>;
min_alloc_set m = {1, 2, 3, 4, 5, 6};
int keys[] = {1, 2, 3, 4, 5, 6};
test(m, std::begin(keys), std::end(keys));
}
}

View File

@ -0,0 +1,83 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <set>
// class set
// insert_return_type insert(node_type&&);
#include <set>
#include <type_traits>
#include "min_allocator.h"
template <class Container>
typename Container::node_type
node_factory(typename Container::key_type const& key)
{
static Container c;
auto p = c.insert(key);
assert(p.second);
return c.extract(p.first);
}
template <class Container>
void test(Container& c)
{
auto* nf = &node_factory<Container>;
for (int i = 0; i != 10; ++i)
{
typename Container::node_type node = nf(i);
assert(!node.empty());
typename Container::insert_return_type irt = c.insert(std::move(node));
assert(node.empty());
assert(irt.inserted);
assert(irt.node.empty());
assert(*irt.position == i);
}
assert(c.size() == 10);
{ // Insert empty node.
typename Container::node_type def;
auto irt = c.insert(std::move(def));
assert(def.empty());
assert(!irt.inserted);
assert(irt.node.empty());
assert(irt.position == c.end());
}
{ // Insert duplicate node.
typename Container::node_type dupl = nf(0);
auto irt = c.insert(std::move(dupl));
assert(dupl.empty());
assert(!irt.inserted);
assert(!irt.node.empty());
assert(irt.position == c.find(0));
assert(irt.node.value() == 0);
}
assert(c.size() == 10);
for (int i = 0; i != 10; ++i)
{
assert(c.count(i) == 1);
}
}
int main()
{
std::set<int> m;
test(m);
std::set<int, std::less<int>, min_allocator<int>> m2;
test(m2);
}

View File

@ -0,0 +1,61 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <set>
// class set
// iterator insert(const_iterator hint, node_type&&);
#include <set>
#include "min_allocator.h"
template <class Container>
typename Container::node_type
node_factory(typename Container::key_type const& key)
{
static Container c;
auto p = c.insert(key);
assert(p.second);
return c.extract(p.first);
}
template <class Container>
void test(Container& c)
{
auto* nf = &node_factory<Container>;
for (int i = 0; i != 10; ++i)
{
typename Container::node_type node = nf(i);
assert(!node.empty());
size_t prev = c.size();
auto it = c.insert(c.end(), std::move(node));
assert(node.empty());
assert(prev + 1 == c.size());
assert(*it == i);
}
assert(c.size() == 10);
for (int i = 0; i != 10; ++i)
{
assert(c.count(i) == 1);
}
}
int main()
{
std::set<int> m;
test(m);
std::set<int, std::less<int>, min_allocator<int>> m2;
test(m2);
}

View File

@ -0,0 +1,145 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
#include <unordered_set>
#include <unordered_map>
#include <set>
#include <map>
#include "min_allocator.h"
using namespace std;
// [container.node.overview] Table 83.
template <class K, class T, class C1, class C2, class H1, class H2, class E1, class E2, class A_set, class A_map>
struct node_compatibility_table
{
static constexpr bool value =
is_same_v<typename map<K, T, C1, A_map>::node_type, typename map<K, T, C2, A_map>::node_type> &&
is_same_v<typename map<K, T, C1, A_map>::node_type, typename multimap<K, T, C2, A_map>::node_type> &&
is_same_v<typename set<K, C1, A_set>::node_type, typename set<K, C2, A_set>::node_type> &&
is_same_v<typename set<K, C1, A_set>::node_type, typename multiset<K, C2, A_set>::node_type> &&
is_same_v<typename unordered_map<K, T, H1, E1, A_map>::node_type, typename unordered_map<K, T, H2, E2, A_map>::node_type> &&
is_same_v<typename unordered_map<K, T, H1, E1, A_map>::node_type, typename unordered_multimap<K, T, H2, E2, A_map>::node_type> &&
is_same_v<typename unordered_set<K, H1, E1, A_set>::node_type, typename unordered_set<K, H2, E2, A_set>::node_type> &&
is_same_v<typename unordered_set<K, H1, E1, A_set>::node_type, typename unordered_multiset<K, H2, E2, A_set>::node_type>;
};
template <class T> struct my_hash
{
using argument_type = T;
using result_type = size_t;
my_hash() = default;
size_t operator()(const T&) const {return 0;}
};
template <class T> struct my_compare
{
my_compare() = default;
bool operator()(const T&, const T&) const {return true;}
};
template <class T> struct my_equal
{
my_equal() = default;
bool operator()(const T&, const T&) const {return true;}
};
struct Static
{
Static() = default;
Static(const Static&) = delete;
Static(Static&&) = delete;
Static& operator=(const Static&) = delete;
Static& operator=(Static&&) = delete;
};
namespace std
{
template <> struct hash<Static>
{
using argument_type = Static;
using result_type = size_t;
hash() = default;
size_t operator()(const Static&) const;
};
}
static_assert(node_compatibility_table<
int, int, std::less<int>, std::less<int>, std::hash<int>,
std::hash<int>, std::equal_to<int>, std::equal_to<int>,
std::allocator<int>,
std::allocator<std::pair<const int, int>>>::value,
"");
static_assert(
node_compatibility_table<int, int, std::less<int>, my_compare<int>,
std::hash<int>, my_hash<int>, std::equal_to<int>,
my_equal<int>, allocator<int>,
allocator<std::pair<const int, int>>>::value,
"");
static_assert(node_compatibility_table<
Static, int, my_compare<Static>, std::less<Static>,
my_hash<Static>, std::hash<Static>, my_equal<Static>,
std::equal_to<Static>, min_allocator<Static>,
min_allocator<std::pair<const Static, int>>>::value,
"");
template <class Container>
void test_node_handle_operations()
{
Container c;
typename Container::node_type nt1, nt2 = c.extract(c.emplace().first);
assert(nt2.get_allocator() == c.get_allocator());
assert(!nt2.empty());
assert(nt1.empty());
std::swap(nt1, nt2);
assert(nt1.get_allocator() == c.get_allocator());
assert(nt2.empty());
}
template <class Container>
void test_node_handle_operations_multi()
{
Container c;
typename Container::node_type nt1, nt2 = c.extract(c.emplace());
assert(nt2.get_allocator() == c.get_allocator());
assert(!nt2.empty());
assert(nt1.empty());
std::swap(nt1, nt2);
assert(nt1.get_allocator() == c.get_allocator());
assert(nt2.empty());
}
template <class Container>
void test_insert_return_type()
{
using irt_type = typename Container::insert_return_type;
}
int main()
{
test_node_handle_operations<std::map<int, int>>();
test_node_handle_operations_multi<std::multimap<int, int>>();
test_node_handle_operations<std::set<int>>();
test_node_handle_operations_multi<std::multiset<int>>();
test_node_handle_operations<std::unordered_map<int, int>>();
test_node_handle_operations_multi<std::unordered_multimap<int, int>>();
test_node_handle_operations<std::unordered_set<int>>();
test_node_handle_operations_multi<std::unordered_multiset<int>>();
test_insert_return_type<std::map<int, int>>();
test_insert_return_type<std::set<int>>();
test_insert_return_type<std::unordered_map<int, int>>();
test_insert_return_type<std::unordered_set<int>>();
}

View File

@ -0,0 +1,67 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <unordered_map>
// class unordered_map
// node_type extract(const_iterator);
#include <unordered_map>
#include "min_allocator.h"
#include "Counter.h"
template <class Container>
void test(Container& c)
{
size_t sz = c.size();
auto some_key = c.cbegin()->first;
for (auto first = c.cbegin(); first != c.cend();)
{
auto key_value = first->first;
typename Container::node_type t = c.extract(first++);
--sz;
assert(t.key() == key_value);
t.key() = some_key;
assert(t.key() == some_key);
assert(t.get_allocator() == c.get_allocator());
assert(sz == c.size());
}
assert(c.size() == 0);
}
int main()
{
{
using map_type = std::unordered_map<int, int>;
map_type m = {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}};
test(m);
}
{
std::unordered_map<Counter<int>, Counter<int>> m =
{{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}};
assert(Counter_base::gConstructed == 12);
test(m);
assert(Counter_base::gConstructed == 0);
}
{
using min_alloc_map =
std::unordered_map<int, int, std::hash<int>, std::equal_to<int>,
min_allocator<std::pair<const int, int>>>;
min_alloc_map m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}};
test(m);
}
}

View File

@ -0,0 +1,76 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <unordered_map>
// class unordered_map
// node_type extract(key_type const&);
#include <unordered_map>
#include "min_allocator.h"
#include "Counter.h"
template <class Container, class KeyTypeIter>
void test(Container& c, KeyTypeIter first, KeyTypeIter last)
{
size_t sz = c.size();
assert((size_t)std::distance(first, last) == sz);
for (KeyTypeIter copy = first; copy != last; ++copy)
{
typename Container::node_type t = c.extract(*copy);
assert(!t.empty());
--sz;
assert(t.key() == *copy);
t.key() = *first; // We should be able to mutate key.
assert(t.key() == *first);
assert(t.get_allocator() == c.get_allocator());
assert(sz == c.size());
}
assert(c.size() == 0);
for (KeyTypeIter copy = first; copy != last; ++copy)
{
typename Container::node_type t = c.extract(*copy);
assert(t.empty());
}
}
int main()
{
{
std::unordered_map<int, int> m = {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}};
int keys[] = {1, 2, 3, 4, 5, 6};
test(m, std::begin(keys), std::end(keys));
}
{
std::unordered_map<Counter<int>, Counter<int>> m =
{{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}};
{
Counter<int> keys[] = {1, 2, 3, 4, 5, 6};
assert(Counter_base::gConstructed == 12+6);
test(m, std::begin(keys), std::end(keys));
}
assert(Counter_base::gConstructed == 0);
}
{
using min_alloc_map =
std::unordered_map<int, int, std::hash<int>, std::equal_to<int>,
min_allocator<std::pair<const int, int>>>;
min_alloc_map m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}};
int keys[] = {1, 2, 3, 4, 5, 6};
test(m, std::begin(keys), std::end(keys));
}
}

View File

@ -0,0 +1,84 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <unordered_map>
// class unordered_map
// insert_return_type insert(node_type&&);
#include <unordered_map>
#include "min_allocator.h"
template <class Container>
typename Container::node_type
node_factory(typename Container::key_type const& key,
typename Container::mapped_type const& mapped)
{
static Container c;
auto p = c.insert({key, mapped});
assert(p.second);
return c.extract(p.first);
}
template <class Container>
void test(Container& c)
{
auto* nf = &node_factory<Container>;
for (int i = 0; i != 10; ++i)
{
typename Container::node_type node = nf(i, i + 1);
assert(!node.empty());
typename Container::insert_return_type irt = c.insert(std::move(node));
assert(node.empty());
assert(irt.inserted);
assert(irt.node.empty());
assert(irt.position->first == i && irt.position->second == i + 1);
}
assert(c.size() == 10);
{ // Insert empty node.
typename Container::node_type def;
auto irt = c.insert(std::move(def));
assert(def.empty());
assert(!irt.inserted);
assert(irt.node.empty());
assert(irt.position == c.end());
}
{ // Insert duplicate node.
typename Container::node_type dupl = nf(0, 42);
auto irt = c.insert(std::move(dupl));
assert(dupl.empty());
assert(!irt.inserted);
assert(!irt.node.empty());
assert(irt.position == c.find(0));
assert(irt.node.key() == 0 && irt.node.mapped() == 42);
}
assert(c.size() == 10);
for (int i = 0; i != 10; ++i)
{
assert(c.count(i) == 1);
assert(c[i] == i + 1);
}
}
int main()
{
std::unordered_map<int, int> m;
test(m);
std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, min_allocator<std::pair<const int, int>>> m2;
test(m2);
}

View File

@ -0,0 +1,64 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <unordered_map>
// class unordered_map
// iterator insert(const_iterator hint, node_type&&);
#include <unordered_map>
#include "min_allocator.h"
template <class Container>
typename Container::node_type
node_factory(typename Container::key_type const& key,
typename Container::mapped_type const& mapped)
{
static Container c;
auto p = c.insert({key, mapped});
assert(p.second);
return c.extract(p.first);
}
template <class Container>
void test(Container& c)
{
auto* nf = &node_factory<Container>;
for (int i = 0; i != 10; ++i)
{
typename Container::node_type node = nf(i, i + 1);
assert(!node.empty());
size_t prev = c.size();
auto it = c.insert(c.end(), std::move(node));
assert(node.empty());
assert(prev + 1 == c.size());
assert(it->first == i);
assert(it->second == i + 1);
}
assert(c.size() == 10);
for (int i = 0; i != 10; ++i)
{
assert(c.count(i) == 1);
assert(c[i] == i + 1);
}
}
int main()
{
std::unordered_map<int, int> m;
test(m);
std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, min_allocator<std::pair<const int, int>>> m2;
test(m2);
}

View File

@ -0,0 +1,67 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <unordered_map>
// class unordered_multimap
// node_type extract(const_iterator);
#include <unordered_map>
#include "min_allocator.h"
#include "Counter.h"
template <class Container>
void test(Container& c)
{
size_t sz = c.size();
auto some_key = c.cbegin()->first;
for (auto first = c.cbegin(); first != c.cend();)
{
auto key_value = first->first;
typename Container::node_type t = c.extract(first++);
--sz;
assert(t.key() == key_value);
t.key() = some_key;
assert(t.key() == some_key);
assert(t.get_allocator() == c.get_allocator());
assert(sz == c.size());
}
assert(c.size() == 0);
}
int main()
{
{
using map_type = std::unordered_multimap<int, int>;
map_type m = {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}};
test(m);
}
{
std::unordered_multimap<Counter<int>, Counter<int>> m =
{{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}};
assert(Counter_base::gConstructed == 12);
test(m);
assert(Counter_base::gConstructed == 0);
}
{
using min_alloc_map =
std::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>,
min_allocator<std::pair<const int, int>>>;
min_alloc_map m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}};
test(m);
}
}

View File

@ -0,0 +1,77 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <unordered_map>
// class unordered_multimap
// node_type extract(key_type const&);
#include <unordered_map>
#include "min_allocator.h"
#include "Counter.h"
template <class Container, class KeyTypeIter>
void test(Container& c, KeyTypeIter first, KeyTypeIter last)
{
size_t sz = c.size();
assert((size_t)std::distance(first, last) == sz);
for (KeyTypeIter copy = first; copy != last; ++copy)
{
typename Container::node_type t = c.extract(*copy);
assert(!t.empty());
--sz;
assert(t.key() == *copy);
t.key() = *first; // We should be able to mutate key.
assert(t.key() == *first);
assert(t.get_allocator() == c.get_allocator());
assert(sz == c.size());
}
assert(c.size() == 0);
for (KeyTypeIter copy = first; copy != last; ++copy)
{
typename Container::node_type t = c.extract(*copy);
assert(t.empty());
}
}
int main()
{
{
std::unordered_multimap<int, int> m =
{{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}};
int keys[] = {1, 2, 3, 4, 5, 6};
test(m, std::begin(keys), std::end(keys));
}
{
std::unordered_multimap<Counter<int>, Counter<int>> m =
{{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}};
{
Counter<int> keys[] = {1, 2, 3, 4, 5, 6};
assert(Counter_base::gConstructed == 12+6);
test(m, std::begin(keys), std::end(keys));
}
assert(Counter_base::gConstructed == 0);
}
{
using min_alloc_map =
std::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>,
min_allocator<std::pair<const int, int>>>;
min_alloc_map m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}};
int keys[] = {1, 2, 3, 4, 5, 6};
test(m, std::begin(keys), std::end(keys));
}
}

View File

@ -0,0 +1,77 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <unordered_map>
// class unordered_multimap
// iterator insert(node_type&&);
#include <unordered_map>
#include "min_allocator.h"
template <class Container>
typename Container::node_type
node_factory(typename Container::key_type const& key,
typename Container::mapped_type const& mapped)
{
static Container c;
auto it = c.insert({key, mapped});
return c.extract(it);
}
template <class Container>
void test(Container& c)
{
auto* nf = &node_factory<Container>;
for (int i = 0; i != 10; ++i)
{
typename Container::node_type node = nf(i, i + 1);
assert(!node.empty());
typename Container::iterator it = c.insert(std::move(node));
assert(node.empty());
assert(it == c.find(i) && it != c.end());
assert(it->first == i && it->second == i + 1);
}
assert(c.size() == 10);
{ // Insert empty node.
typename Container::node_type def;
auto it = c.insert(std::move(def));
assert(def.empty());
assert(it == c.end());
}
{ // Insert duplicate node.
typename Container::node_type dupl = nf(0, 42);
auto it = c.insert(std::move(dupl));
assert(dupl.empty());
assert(it != c.end() && it->second == 42);
}
assert(c.size() == 11);
assert(c.count(0) == 2);
for (int i = 1; i != 10; ++i)
{
assert(c.count(i) == 1);
assert(c.find(i)->second == i + 1);
}
}
int main()
{
std::unordered_multimap<int, int> m;
test(m);
std::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>, min_allocator<std::pair<const int, int>>> m2;
test(m2);
}

View File

@ -0,0 +1,63 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <unordered_map>
// class unordered_multimap
// iterator insert(const_iterator hint, node_type&&);
#include <unordered_map>
#include "min_allocator.h"
template <class Container>
typename Container::node_type
node_factory(typename Container::key_type const& key,
typename Container::mapped_type const& mapped)
{
static Container c;
auto it = c.insert({key, mapped});
return c.extract(it);
}
template <class Container>
void test(Container& c)
{
auto* nf = &node_factory<Container>;
for (int i = 0; i != 10; ++i)
{
typename Container::node_type node = nf(i, i + 1);
assert(!node.empty());
size_t prev = c.size();
auto it = c.insert(c.end(), std::move(node));
assert(node.empty());
assert(prev + 1 == c.size());
assert(it->first == i);
assert(it->second == i + 1);
}
assert(c.size() == 10);
for (int i = 0; i != 10; ++i)
{
assert(c.count(i) == 1);
assert(c.find(i)->second == i + 1);
}
}
int main()
{
std::unordered_multimap<int, int> m;
test(m);
std::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>, min_allocator<std::pair<const int, int>>> m2;
test(m2);
}

View File

@ -0,0 +1,60 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <unordered_set>
// class unordered_multiset
// node_type extract(const_iterator);
#include <unordered_set>
#include "min_allocator.h"
#include "Counter.h"
template <class Container>
void test(Container& c)
{
size_t sz = c.size();
for (auto first = c.cbegin(); first != c.cend();)
{
auto key_value = *first;
typename Container::node_type t = c.extract(first++);
--sz;
assert(t.value() == key_value);
assert(t.get_allocator() == c.get_allocator());
assert(sz == c.size());
}
assert(c.size() == 0);
}
int main()
{
{
using set_type = std::unordered_multiset<int>;
set_type m = {1, 2, 3, 4, 5, 6};
test(m);
}
{
std::unordered_multiset<Counter<int>> m = {1, 2, 3, 4, 5, 6};
assert(Counter_base::gConstructed == 6);
test(m);
assert(Counter_base::gConstructed == 0);
}
{
using min_alloc_set = std::unordered_multiset<int, std::hash<int>, std::equal_to<int>, min_allocator<int>>;
min_alloc_set m = {1, 2, 3, 4, 5, 6};
test(m);
}
}

View File

@ -0,0 +1,71 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <unordered_multiset>
// class unordered_multiset
// node_type extract(key_type const&);
#include <unordered_set>
#include "min_allocator.h"
#include "Counter.h"
template <class Container, class KeyTypeIter>
void test(Container& c, KeyTypeIter first, KeyTypeIter last)
{
size_t sz = c.size();
assert((size_t)std::distance(first, last) == sz);
for (KeyTypeIter copy = first; copy != last; ++copy)
{
typename Container::node_type t = c.extract(*copy);
assert(!t.empty());
--sz;
assert(t.value() == *copy);
assert(t.get_allocator() == c.get_allocator());
assert(sz == c.size());
}
assert(c.size() == 0);
for (KeyTypeIter copy = first; copy != last; ++copy)
{
typename Container::node_type t = c.extract(*copy);
assert(t.empty());
}
}
int main()
{
{
std::unordered_multiset<int> m = {1, 2, 3, 4, 5, 6};
int keys[] = {1, 2, 3, 4, 5, 6};
test(m, std::begin(keys), std::end(keys));
}
{
std::unordered_multiset<Counter<int>> m = {1, 2, 3, 4, 5, 6};
{
Counter<int> keys[] = {1, 2, 3, 4, 5, 6};
assert(Counter_base::gConstructed == 6+6);
test(m, std::begin(keys), std::end(keys));
}
assert(Counter_base::gConstructed == 0);
}
{
using min_alloc_set = std::unordered_multiset<int, std::hash<int>, std::equal_to<int>, min_allocator<int>>;
min_alloc_set m = {1, 2, 3, 4, 5, 6};
int keys[] = {1, 2, 3, 4, 5, 6};
test(m, std::begin(keys), std::end(keys));
}
}

View File

@ -0,0 +1,76 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <unordered_set>
// class unordered_multiset
// iterator insert(node_type&&);
#include <unordered_set>
#include <type_traits>
#include "min_allocator.h"
template <class Container>
typename Container::node_type
node_factory(typename Container::key_type const& key)
{
static Container c;
auto it = c.insert(key);
return c.extract(it);
}
template <class Container>
void test(Container& c)
{
auto* nf = &node_factory<Container>;
for (int i = 0; i != 10; ++i)
{
typename Container::node_type node = nf(i);
assert(!node.empty());
typename Container::iterator it = c.insert(std::move(node));
assert(node.empty());
assert(it == c.find(i) && it != c.end());
assert(*it == i);
assert(node.empty());
}
assert(c.size() == 10);
{ // Insert empty node.
typename Container::node_type def;
auto it = c.insert(std::move(def));
assert(def.empty());
assert(it == c.end());
}
{ // Insert duplicate node.
typename Container::node_type dupl = nf(0);
auto it = c.insert(std::move(dupl));
assert(*it == 0);
}
assert(c.size() == 11);
assert(c.count(0) == 2);
for (int i = 1; i != 10; ++i)
{
assert(c.count(i) == 1);
}
}
int main()
{
std::unordered_multiset<int> m;
test(m);
std::unordered_multiset<int, std::hash<int>, std::equal_to<int>, min_allocator<int>> m2;
test(m2);
}

View File

@ -0,0 +1,59 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <unordered_set>
// class unordered_multiset
// iterator insert(const_iterator hint, node_type&&);
#include <unordered_set>
#include "min_allocator.h"
template <class Container>
typename Container::node_type
node_factory(typename Container::key_type const& key)
{
static Container c;
auto it = c.insert(key);
return c.extract(it);
}
template <class Container>
void test(Container& c)
{
auto* nf = &node_factory<Container>;
for (int i = 0; i != 10; ++i)
{
typename Container::node_type node = nf(i);
assert(!node.empty());
size_t prev = c.size();
auto it = c.insert(c.end(), std::move(node));
assert(prev + 1 == c.size());
assert(*it == i);
}
assert(c.size() == 10);
for (int i = 0; i != 10; ++i)
{
assert(c.count(i) == 1);
}
}
int main()
{
std::unordered_multiset<int> m;
test(m);
std::unordered_multiset<int, std::hash<int>, std::equal_to<int>, min_allocator<int>> m2;
test(m2);
}

View File

@ -0,0 +1,60 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <unordered_set>
// class unordered_set
// node_type extract(const_iterator);
#include <unordered_set>
#include "min_allocator.h"
#include "Counter.h"
template <class Container>
void test(Container& c)
{
size_t sz = c.size();
for (auto first = c.cbegin(); first != c.cend();)
{
auto key_value = *first;
typename Container::node_type t = c.extract(first++);
--sz;
assert(t.value() == key_value);
assert(t.get_allocator() == c.get_allocator());
assert(sz == c.size());
}
assert(c.size() == 0);
}
int main()
{
{
using set_type = std::unordered_set<int>;
set_type m = {1, 2, 3, 4, 5, 6};
test(m);
}
{
std::unordered_set<Counter<int>> m = {1, 2, 3, 4, 5, 6};
assert(Counter_base::gConstructed == 6);
test(m);
assert(Counter_base::gConstructed == 0);
}
{
using min_alloc_set = std::unordered_set<int, std::hash<int>, std::equal_to<int>, min_allocator<int>>;
min_alloc_set m = {1, 2, 3, 4, 5, 6};
test(m);
}
}

View File

@ -0,0 +1,71 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <unordered_set>
// class unordered_set
// node_type extract(key_type const&);
#include <unordered_set>
#include "min_allocator.h"
#include "Counter.h"
template <class Container, class KeyTypeIter>
void test(Container& c, KeyTypeIter first, KeyTypeIter last)
{
size_t sz = c.size();
assert((size_t)std::distance(first, last) == sz);
for (KeyTypeIter copy = first; copy != last; ++copy)
{
typename Container::node_type t = c.extract(*copy);
assert(!t.empty());
--sz;
assert(t.value() == *copy);
assert(t.get_allocator() == c.get_allocator());
assert(sz == c.size());
}
assert(c.size() == 0);
for (KeyTypeIter copy = first; copy != last; ++copy)
{
typename Container::node_type t = c.extract(*copy);
assert(t.empty());
}
}
int main()
{
{
std::unordered_set<int> m = {1, 2, 3, 4, 5, 6};
int keys[] = {1, 2, 3, 4, 5, 6};
test(m, std::begin(keys), std::end(keys));
}
{
std::unordered_set<Counter<int>> m = {1, 2, 3, 4, 5, 6};
{
Counter<int> keys[] = {1, 2, 3, 4, 5, 6};
assert(Counter_base::gConstructed == 6+6);
test(m, std::begin(keys), std::end(keys));
}
assert(Counter_base::gConstructed == 0);
}
{
using min_alloc_set = std::unordered_set<int, std::hash<int>, std::equal_to<int>, min_allocator<int>>;
min_alloc_set m = {1, 2, 3, 4, 5, 6};
int keys[] = {1, 2, 3, 4, 5, 6};
test(m, std::begin(keys), std::end(keys));
}
}

View File

@ -0,0 +1,83 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <unordered_set>
// class unordered_set
// insert_return_type insert(node_type&&);
#include <unordered_set>
#include <type_traits>
#include "min_allocator.h"
template <class Container>
typename Container::node_type
node_factory(typename Container::key_type const& key)
{
static Container c;
auto p = c.insert(key);
assert(p.second);
return c.extract(p.first);
}
template <class Container>
void test(Container& c)
{
auto* nf = &node_factory<Container>;
for (int i = 0; i != 10; ++i)
{
typename Container::node_type node = nf(i);
assert(!node.empty());
typename Container::insert_return_type irt = c.insert(std::move(node));
assert(node.empty());
assert(irt.inserted);
assert(irt.node.empty());
assert(*irt.position == i);
}
assert(c.size() == 10);
{ // Insert empty node.
typename Container::node_type def;
auto irt = c.insert(std::move(def));
assert(def.empty());
assert(!irt.inserted);
assert(irt.node.empty());
assert(irt.position == c.end());
}
{ // Insert duplicate node.
typename Container::node_type dupl = nf(0);
auto irt = c.insert(std::move(dupl));
assert(dupl.empty());
assert(!irt.inserted);
assert(!irt.node.empty());
assert(irt.position == c.find(0));
assert(irt.node.value() == 0);
}
assert(c.size() == 10);
for (int i = 0; i != 10; ++i)
{
assert(c.count(i) == 1);
}
}
int main()
{
std::unordered_set<int> m;
test(m);
std::unordered_set<int, std::hash<int>, std::equal_to<int>, min_allocator<int>> m2;
test(m2);
}

View File

@ -0,0 +1,61 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <unordered_set>
// class unordered_set
// iterator insert(const_iterator hint, node_type&&);
#include <unordered_set>
#include "min_allocator.h"
template <class Container>
typename Container::node_type
node_factory(typename Container::key_type const& key)
{
static Container c;
auto p = c.insert(key);
assert(p.second);
return c.extract(p.first);
}
template <class Container>
void test(Container& c)
{
auto* nf = &node_factory<Container>;
for (int i = 0; i != 10; ++i)
{
typename Container::node_type node = nf(i);
assert(!node.empty());
size_t prev = c.size();
auto it = c.insert(c.end(), std::move(node));
assert(node.empty());
assert(prev + 1 == c.size());
assert(*it == i);
}
assert(c.size() == 10);
for (int i = 0; i != 10; ++i)
{
assert(c.count(i) == 1);
}
}
int main()
{
std::unordered_set<int> m;
test(m);
std::unordered_set<int, std::hash<int>, std::equal_to<int>, min_allocator<int>> m2;
test(m2);
}

View File

@ -23,7 +23,7 @@ public:
Counter() : data_() { ++gConstructed; }
Counter(const T &data) : data_(data) { ++gConstructed; }
Counter(const Counter& rhs) : data_(rhs.data_) { ++gConstructed; }
Counter& operator=(const Counter& rhs) { ++gConstructed; data_ = rhs.data_; return *this; }
Counter& operator=(const Counter& rhs) { data_ = rhs.data_; return *this; }
#if TEST_STD_VER >= 11
Counter(Counter&& rhs) : data_(std::move(rhs.data_)) { ++gConstructed; }
Counter& operator=(Counter&& rhs) { ++gConstructed; data_ = std::move(rhs.data_); return *this; }
@ -49,7 +49,7 @@ struct hash<Counter<T> >
typedef Counter<T> argument_type;
typedef std::size_t result_type;
std::size_t operator()(const Counter<T>& x) const {return std::hash<T>(x.get());}
std::size_t operator()(const Counter<T>& x) const {return std::hash<T>()(x.get());}
};
}