Compare commits

...

107 Commits

Author SHA1 Message Date
Christian Mazakas 0c93fbc330 Make typedef private and rename it so older versions of msvc don't erroneously treat the typedef like it's in scope when doing template instantiation 2023-02-13 09:10:21 -08:00
Christian Mazakas b8ff76f4ab Manually implement node_handle_base's default constructor instead of defaulting it which can delete it on older toolchains 2023-02-10 15:16:59 -08:00
Christian Mazakas 5df80086ed Add foa-based node containers to extract tests in transparent_tests 2023-02-10 14:19:20 -08:00
Christian Mazakas f9c32e7f8c Clean up impl of node_handle 2023-02-10 14:19:01 -08:00
Christian Mazakas 21e673c697 Begin cleanup of node_handle implementation 2023-02-09 15:59:23 -08:00
Christian Mazakas b96dd2184f Add foa-based node containers to node_handle_tests 2023-02-08 15:08:51 -08:00
Christian Mazakas 9636875596 Fix incorrect placement new of allocator type by reifying ad hoc node handle implementations into a base class 2023-02-08 10:36:19 -08:00
Christian Mazakas bd6829220c Add extract/insert semantics to foa-based node set, add more tests 2023-02-07 15:17:25 -08:00
Christian Mazakas 71bf336c9d Add missing empty_ initialization to move constructor of node_type 2023-02-07 10:08:58 -08:00
Christian Mazakas b7c1e6a184 Remove print statements 2023-02-07 10:08:34 -08:00
Christian Mazakas 77edd24b4e Interim checkin of attempt at extract/insert node handles 2023-02-06 15:56:55 -08:00
Christian Mazakas b7032baaf4 fixup osx fix 2023-02-03 10:02:49 -08:00
Christian Mazakas 6580dc8d80 Add regression test for test::exception::less 2023-02-03 10:02:28 -08:00
Christian Mazakas 5384edd568 Attempt osx ci fix by fixing logic buf in less_impl for test::exception::less 2023-02-02 13:32:08 -08:00
Christian Mazakas 2a7a8f55e1 Revert OSX CI experiment as it breaks emplace_tests 2023-02-01 10:49:20 -08:00
Christian Mazakas 18a664c4a6 Experiment for failing OSX CI 2023-02-01 10:25:50 -08:00
Christian Mazakas e1b394d5b2 Disable immovable test for libstdc++ versions below 6.0 as their std::pair implementation doesn't support immovable types 2023-02-01 09:02:05 -08:00
Christian Mazakas dc548a1a9e Update compare_range() to skip size check and use direct comparison function 2023-01-31 15:59:29 -08:00
Christian Mazakas 2787717d78 Update compare_range to use BOOST_TEST_ALL_WITH in lieu of homegrown implementation 2023-01-31 13:55:06 -08:00
Christian Mazakas d6ba04ca4b Remove use of unevaluated function in init_type_insert_tests for older versions of gcc 2023-01-31 13:45:29 -08:00
Christian Mazakas 43add11970 Add macos-12 to GHA 2023-01-31 13:45:10 -08:00
Christian Mazakas 8e45197d4d Add -Wunused-template only to clang-14 builds 2023-01-31 13:44:57 -08:00
Christian Mazakas a46220986f Replace usage of rote try-catch with corresponding Boost versions 2023-01-31 10:32:06 -08:00
Christian Mazakas 16099478db Clean up implementation of emplace_dispatch(false_type) 2023-01-31 10:31:52 -08:00
Christian Mazakas e5320df017 Fix msvc warnings 2023-01-31 09:03:25 -08:00
Christian Mazakas b9fcfeb24e Update foa table to support immovable types in the case of the node-based maps 2023-01-30 13:55:50 -08:00
Christian Mazakas f1aeb3b099 Update init_type_insert_tests for node-based foa containers 2023-01-30 13:55:50 -08:00
Christian Mazakas 5b706bb7b5 Update node-based foa containers to default their element_type default constructor and delete the copy constructor to get the appropriate type-based optimizations 2023-01-30 13:55:50 -08:00
Christian Mazakas fd7d888832 Add missing test back in for non-foa runs 2023-01-30 13:55:50 -08:00
Christian Mazakas 827c69eb1a Conditionally exclude node_map from non-foa test runs 2023-01-30 13:55:50 -08:00
Christian Mazakas 9973b3f8a8 Comment tests back in 2023-01-30 13:55:50 -08:00
joaquintides e6f911e815 provide erase_on_exit ctor 2023-01-30 13:55:50 -08:00
joaquintides 53e4531295 fixed bug with dangling moved element on throwing rehash during merge 2023-01-30 13:55:50 -08:00
Christian Mazakas 8da44f4f46 Check in interim tests for easy debugging between team members 2023-01-30 13:55:50 -08:00
Christian Mazakas dddfbf8aa8 Add node-based foa containers to swap_exception_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas a66eedef58 Add node-based foa containers to insert_exception_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 202049ddc0 Add node-based foa containers to merge_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 000833d647 fixup insert_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas d84e6f7be2 fixup assign_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 8acfccdf6e fixup constructor_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas c85dd289f9 Add node-based foa containers to simple_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 8ac6019d30 Add node-based foa containers to incomplete_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 9602799710 Add node-based foa containers to link tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 217a171b33 Add node-based foa containers to noexcept_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas b372ab6641 Add node-based foa containers to compile_map 2023-01-30 13:55:50 -08:00
Christian Mazakas 140cb56e2b Add node-based foa containers to compile_set 2023-01-30 13:55:50 -08:00
Christian Mazakas 8b842c4640 fixup fwd_set_test 2023-01-30 13:55:50 -08:00
Christian Mazakas 9b2ecd6ec5 Add node-based foa containers to fwd_map_test 2023-01-30 13:55:50 -08:00
Christian Mazakas 351e5ae41a Add node-based foa containers to fwd_set_test 2023-01-30 13:55:50 -08:00
Christian Mazakas 1c5733ed15 Add node-based foa containers to exception tests 2023-01-30 13:55:50 -08:00
Christian Mazakas cd44e0ba08 Add node-based foa containers to max_load_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 3363261ad8 Add node-based foa containers to scary_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 58b8b00233 Add node-based foa containers to reserve_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 6474f3c8d3 Add node-based foa containers to transparent_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 63269d2115 Add node-based foa container to scoped_allocator tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 0925a99d98 Add node-based foa containers to swap_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 1b23d08941 Add node-based foa containers to equality_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 28142b6251 Add node-based foa container to at_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas b60f2ce22c Add rehash tests proving that elements are not relocated for node-based containers 2023-01-30 13:55:50 -08:00
Christian Mazakas 473ed9b88b Update check used to determine when to move during rehashing to accomodate node-based containers 2023-01-30 13:55:50 -08:00
Christian Mazakas c554c5b1c9 Add node-based foa containers to rehash_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas e244b35d23 fixup load_factor_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas f7bfb85d84 Add node-based foa containers to load_factor_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 5e0257cb08 Add node-based foa containers to erase_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 64721fa1ef Clean up insert tests to use more idiomatic UNORDERED_TEST macros 2023-01-30 13:55:50 -08:00
Christian Mazakas 5bfc77c3e4 Add node-based foa containers to emplace_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas aaf0e40247 Update unordered_node_map to be a proper copy of unordered_flat_map 2023-01-30 13:55:50 -08:00
Christian Mazakas 8e86a263fc Add node-based foa containers to insert_hint_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas a5a5b75dcc Add node-based foa containers to post_move_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas b57b51b036 Remove moved_value_from() in favor of overloading move() in container type traits 2023-01-30 13:55:50 -08:00
Christian Mazakas 91b3863c77 Add node-based foa containers to erase_if tests 2023-01-30 13:55:50 -08:00
Christian Mazakas b4a23a875c fixup copy_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas f0afa5aaef Add node-based foa containers to equivalent_keys_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 7ce7ef5050 Add moved_value_from() to container policies, enabling proper move semantics for node-based containers in the case of unequal allocators 2023-01-30 13:55:50 -08:00
Christian Mazakas a3d4a078de Add node-based foa containers to move_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 1e61423eac Prove relevance of strong typedef for node-based foa containers 2023-01-30 13:55:50 -08:00
Christian Mazakas 904e806b1e Update node containers to no longer memcpy their pointer arrays 2023-01-30 13:55:50 -08:00
Christian Mazakas 3201a014c4 Add node-based foa containers to copy_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 1a87580c58 Add node-based foa containers to contains_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas ab58b613c9 Remove multiset from set_tests2_impl call 2023-01-30 13:55:50 -08:00
Christian Mazakas bb57d91675 Update insert_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 7d1e64a3c6 Update node set to conditionally use strong vs weak typedef 2023-01-30 13:55:50 -08:00
Christian Mazakas ff956ad080 Update flat_set to eschew strong typedef 2023-01-30 13:55:50 -08:00
Christian Mazakas d9bf1e435c Revert perfect forwarding when hashing for transparent ops 2023-01-30 13:55:50 -08:00
Christian Mazakas eb6d0d1f66 remove print statements 2023-01-30 13:55:50 -08:00
Christian Mazakas bce898165c Add transparent insert, show we don't need a strong typedef 2023-01-30 13:55:50 -08:00
Christian Mazakas e3c66a5e82 Remove print statements 2023-01-30 13:55:50 -08:00
Christian Mazakas b167ab7d84 Update code to use strong typedefs 2023-01-30 13:55:50 -08:00
Christian Mazakas 71fd0c07ed Add new failing test case 2023-01-30 13:55:50 -08:00
Christian Mazakas 130b483123 Add node-based foa containers to assign_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 03ee5d135b Add node-based foa containers to constructor_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 72841102f6 Add node-based foa containers to find_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas cc6748e2b1 Flesh out insert_tests for node-based foa set 2023-01-30 13:55:50 -08:00
Christian Mazakas f99decc0ca Add unordered_node_set to the insert_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas ae10a1e0df Add unordered_node_set 2023-01-30 13:55:50 -08:00
Christian Mazakas b1e497cd1d Get test suite passing 2023-01-30 13:55:50 -08:00
Christian Mazakas cbe19722a3 interim commit 2023-01-30 13:55:50 -08:00
Christian Mazakas dcff2ac5b5 Pull type policies into detail namespace 2023-01-30 13:55:50 -08:00
Christian Mazakas cb4e636d78 Implement new type policy requirements for flat containers 2023-01-30 13:55:50 -08:00
Christian Mazakas 6e41418744 Reinstate insert_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 1d8d065113 Update interim prototype to eschew allocator wrapper and instead use extended map_types 2023-01-30 13:55:50 -08:00
Christian Mazakas a858517c49 Update clang to warn on unused static function templates 2023-01-30 13:55:50 -08:00
Christian Mazakas 2cdcbd24f5 Catch remaining places where value_type was used instead of storage_type 2023-01-30 13:55:50 -08:00
Christian Mazakas 721d8713cd Extend insert_tests to test unordered_node_map wherever unordered_flat_map is also tested 2023-01-30 13:55:50 -08:00
Christian Mazakas 62e1d3eafb Remove bad static_assert() from insert_tests 2023-01-30 13:55:50 -08:00
Christian Mazakas 3744bafa55 Update implementation to use storage_type when allocating arrays and constructing/destroying elements 2023-01-30 13:55:50 -08:00
Christian Mazakas f034e43b74 Get simple prototype of insert_tests working for unordered_node_map 2023-01-30 13:55:50 -08:00
54 changed files with 4955 additions and 1263 deletions
+2 -1
View File
@@ -72,7 +72,8 @@ jobs:
compiler: clang-14, cxxstd: '17,20,2b', os: ubuntu-22.04, ccache_key: "san2" }
# OSX, clang
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: macos-11, sanitize: yes }
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: macos-11, }
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: macos-12, sanitize: yes }
timeout-minutes: 120
runs-on: ${{matrix.os}}
+142 -65
View File
@@ -11,6 +11,8 @@
#ifndef BOOST_UNORDERED_DETAIL_FOA_HPP
#define BOOST_UNORDERED_DETAIL_FOA_HPP
#include <iostream>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
@@ -805,12 +807,15 @@ class table;
/* internal conversion from const_iterator to iterator */
class const_iterator_cast_tag {};
template<typename Value,typename Group,bool Const>
template<typename TypePolicy,typename Group,bool Const>
class table_iterator
{
using type_policy=TypePolicy;
using table_element_type=typename type_policy::element_type;
public:
using difference_type=std::ptrdiff_t;
using value_type=Value;
using value_type=typename type_policy::value_type;
using pointer=
typename std::conditional<Const,value_type const*,value_type*>::type;
using reference=
@@ -821,14 +826,15 @@ public:
table_iterator()=default;
template<bool Const2,typename std::enable_if<!Const2>::type* =nullptr>
table_iterator(const table_iterator<Value,Group,Const2>& x):
table_iterator(const table_iterator<TypePolicy,Group,Const2>& x):
pc{x.pc},p{x.p}{}
table_iterator(
const_iterator_cast_tag, const table_iterator<Value,Group,true>& x):
const_iterator_cast_tag, const table_iterator<TypePolicy,Group,true>& x):
pc{x.pc},p{x.p}{}
inline reference operator*()const noexcept{return *p;}
inline pointer operator->()const noexcept{return p;}
inline reference operator*()const noexcept{return type_policy::value_from(*p);}
inline pointer operator->()const noexcept
{return std::addressof(type_policy::value_from(*p));}
inline table_iterator& operator++()noexcept{increment();return *this;}
inline table_iterator operator++(int)noexcept
{auto x=*this;increment();return x;}
@@ -843,9 +849,9 @@ private:
template<typename,typename,bool> friend class table_iterator;
template<typename,typename,typename,typename> friend class table;
table_iterator(Group* pg,std::size_t n,const Value* p_):
table_iterator(Group* pg,std::size_t n,const table_element_type* p_):
pc{reinterpret_cast<unsigned char*>(const_cast<Group*>(pg))+n},
p{const_cast<Value*>(p_)}
p{const_cast<table_element_type*>(p_)}
{}
inline std::size_t rebase() noexcept
@@ -879,8 +885,8 @@ private:
}
}
unsigned char *pc=nullptr;
Value *p=nullptr;
unsigned char *pc=nullptr;
table_element_type *p=nullptr;
};
/* table_arrays controls allocation, initialization and deallocation of
@@ -921,7 +927,10 @@ struct table_arrays
template<typename Allocator>
static table_arrays new_(Allocator& al,std::size_t n)
{
using alloc_traits=boost::allocator_traits<Allocator>;
// using alloc_traits=boost::allocator_traits<Allocator>;
using storage_allocator=
typename boost::allocator_rebind<Allocator, Value>::type;
using storage_traits=boost::allocator_traits<storage_allocator>;
auto groups_size_index=size_index_for<group_type,size_policy>(n);
auto groups_size=size_policy::size(groups_size_index);
@@ -931,8 +940,9 @@ struct table_arrays
arrays.groups=dummy_groups<group_type,size_policy::min_size()>();
}
else{
arrays.elements=
boost::to_address(alloc_traits::allocate(al,buffer_size(groups_size)));
auto sal=storage_allocator(al);
arrays.elements=boost::to_address(
storage_traits::allocate(sal,buffer_size(groups_size)));
/* Align arrays.groups to sizeof(group_type). table_iterator critically
* depends on such alignment for its increment operation.
@@ -956,13 +966,15 @@ struct table_arrays
template<typename Allocator>
static void delete_(Allocator& al,table_arrays& arrays)noexcept
{
using alloc_traits=boost::allocator_traits<Allocator>;
using storage_alloc=typename boost::allocator_rebind<Allocator,Value>::type;
using alloc_traits=boost::allocator_traits<storage_alloc>;
using pointer=typename alloc_traits::pointer;
using pointer_traits=boost::pointer_traits<pointer>;
auto sal=storage_alloc(al);
if(arrays.elements){
alloc_traits::deallocate(
al,pointer_traits::pointer_to(*arrays.elements),
sal,pointer_traits::pointer_to(*arrays.elements),
buffer_size(arrays.groups_size_mask+1));
}
}
@@ -1174,6 +1186,7 @@ public:
using key_type=typename type_policy::key_type;
using init_type=typename type_policy::init_type;
using value_type=typename type_policy::value_type;
using element_type=typename type_policy::element_type;
private:
static constexpr bool has_mutable_iterator=
@@ -1189,10 +1202,10 @@ public:
using const_reference=const value_type&;
using size_type=std::size_t;
using difference_type=std::ptrdiff_t;
using const_iterator=table_iterator<value_type,group_type,true>;
using const_iterator=table_iterator<type_policy,group_type,true>;
using iterator=typename std::conditional<
has_mutable_iterator,
table_iterator<value_type,group_type,false>,
table_iterator<type_policy,group_type,false>,
const_iterator>::type;
table(
@@ -1243,15 +1256,15 @@ public:
/* This works because subsequent x.clear() does not depend on the
* elements' values.
*/
x.for_all_elements([this](value_type* p){
unchecked_insert(type_policy::move(*p));
x.for_all_elements([this](element_type* p){
unchecked_insert(type_policy::move(type_policy::value_from(*p)));
});
}
}
~table()noexcept
{
for_all_elements([this](value_type* p){
for_all_elements([this](element_type* p){
destroy_element(p);
});
delete_arrays(arrays);
@@ -1340,8 +1353,8 @@ public:
/* This works because subsequent x.clear() does not depend on the
* elements' values.
*/
x.for_all_elements([this](value_type* p){
unchecked_insert(type_policy::move(*p));
x.for_all_elements([this](element_type* p){
unchecked_insert(type_policy::move(type_policy::value_from(*p)));
});
}
}
@@ -1375,14 +1388,18 @@ public:
template<typename... Args>
BOOST_FORCEINLINE std::pair<iterator,bool> emplace(Args&&... args)
{
using emplace_type = typename std::conditional<
/* We dispatch based on whether or not the value_type is constructible from
* an rvalue refernce to the deduced emplace_type. We do this specifically
* for the csae of the node-based containers. To this end, we're able to
* avoid allocating a node when a duplicate element is attempted to be
* inserted. For immovable types, we instead dispatch to the routine that
* unconditionally allocates via `type_policy::construct()`.
*/
return emplace_dispatch(
std::is_constructible<
init_type, Args...
>::value,
init_type,
value_type
>::type;
return emplace_impl(emplace_type(std::forward<Args>(args)...));
value_type,
emplace_type<Args...>&&>{},
std::forward<Args>(args)...);
}
template<typename Key,typename... Args>
@@ -1409,6 +1426,14 @@ public:
BOOST_FORCEINLINE std::pair<iterator,bool>
insert(value_type&& x){return emplace_impl(std::move(x));}
template<typename T=element_type>
BOOST_FORCEINLINE
typename std::enable_if<
!std::is_same<T,value_type>::value,
std::pair<iterator,bool>
>::type
insert(element_type&& x){return emplace_impl(std::move(x));}
template<
bool dependent_value=false,
typename std::enable_if<
@@ -1483,14 +1508,21 @@ public:
}
}
element_type extract(const_iterator pos)
{
BOOST_ASSERT(pos!=end());
erase_on_exit e{*this,iterator{const_iterator_cast_tag{},pos}};
(void)e;
return std::move(*pos.p);
}
// TODO: should we accept different allocator too?
template<typename Hash2,typename Pred2>
void merge(table<TypePolicy,Hash2,Pred2,Allocator>& x)
{
x.for_all_elements([&,this](group_type* pg,unsigned int n,value_type* p){
if(emplace_impl(type_policy::move(*p)).second){
x.erase(iterator{pg,n,p});
}
x.for_all_elements([&,this](group_type* pg,unsigned int n,element_type* p){
erase_on_exit e{x,{pg,n,p}};
if(!emplace_impl(type_policy::move(*p)).second)e.rollback();
});
}
@@ -1550,7 +1582,16 @@ public:
private:
template<typename,typename,typename,typename> friend class table;
using arrays_type=table_arrays<value_type,group_type,size_policy>;
using arrays_type=table_arrays<element_type,group_type,size_policy>;
template<typename... Args>
using emplace_type = typename std::conditional<
std::is_constructible<
init_type,Args...
>::value,
init_type,
value_type
>::type;
struct clear_on_exit
{
@@ -1558,6 +1599,18 @@ private:
table& x;
};
struct erase_on_exit
{
erase_on_exit(table& x_,iterator it_):x{x_},it{it_}{}
~erase_on_exit(){if(!rollback_)x.erase(it);}
void rollback(){rollback_=true;}
table& x;
iterator it;
bool rollback_=false;
};
Hash& h(){return hash_base::get();}
const Hash& h()const{return hash_base::get();}
Pred& pred(){return pred_base::get();}
@@ -1576,13 +1629,13 @@ private:
}
template<typename... Args>
void construct_element(value_type* p,Args&&... args)
void construct_element(element_type* p,Args&&... args)
{
alloc_traits::construct(al(),p,std::forward<Args>(args)...);
type_policy::construct(al(),p,std::forward<Args>(args)...);
}
template<typename... Args>
void construct_element(value_type* p,try_emplace_args_t,Args&&... args)
void construct_element(element_type* p,try_emplace_args_t,Args&&... args)
{
construct_element_from_try_emplace_args(
p,
@@ -1592,9 +1645,9 @@ private:
template<typename Key,typename... Args>
void construct_element_from_try_emplace_args(
value_type* p,std::false_type,Key&& x,Args&&... args)
element_type* p,std::false_type,Key&& x,Args&&... args)
{
alloc_traits::construct(
type_policy::construct(
al(),p,
std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(x)),
@@ -1607,21 +1660,21 @@ private:
template<typename Key>
void construct_element_from_try_emplace_args(
value_type* p,std::true_type,Key&& x)
element_type* p,std::true_type,Key&& x)
{
alloc_traits::construct(al(),p,std::forward<Key>(x));
type_policy::construct(al(),p,std::forward<Key>(x));
}
void destroy_element(value_type* p)noexcept
void destroy_element(element_type* p)noexcept
{
alloc_traits::destroy(al(),p);
type_policy::destroy(al(),p);
}
struct destroy_element_on_exit
{
~destroy_element_on_exit(){this_->destroy_element(p);}
table *this_;
value_type *p;
table *this_;
element_type *p;
};
void copy_elements_from(const table& x)
@@ -1632,7 +1685,7 @@ private:
fast_copy_elements_from(x);
}
else{
x.for_all_elements([this](const value_type* p){
x.for_all_elements([this](const element_type* p){
unchecked_insert(*p);
});
}
@@ -1657,9 +1710,9 @@ private:
bool,
#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<50000)
/* std::is_trivially_copy_constructible not provided */
boost::has_trivial_copy<value_type>::value
boost::has_trivial_copy<element_type>::value
#else
std::is_trivially_copy_constructible<value_type>::value
std::is_trivially_copy_constructible<element_type>::value
#endif
&&(
is_std_allocator<Allocator>::value||
@@ -1683,14 +1736,14 @@ private:
{
std::size_t num_constructed=0;
BOOST_TRY{
x.for_all_elements([&,this](const value_type* p){
x.for_all_elements([&,this](const element_type* p){
construct_element(arrays.elements+(p-x.arrays.elements),*p);
++num_constructed;
});
}
BOOST_CATCH(...){
if(num_constructed){
x.for_all_elements_while([&,this](const value_type* p){
x.for_all_elements_while([&,this](const element_type* p){
destroy_element(arrays.elements+(p-x.arrays.elements));
return --num_constructed!=0;
});
@@ -1760,7 +1813,7 @@ private:
return size_policy::position(hash,arrays_.groups_size_index);
}
static inline void prefetch_elements(const value_type* p)
static inline void prefetch_elements(const element_type* p)
{
/* We have experimentally confirmed that ARM architectures get a higher
* speedup when around the first half of the element slots in a group are
@@ -1821,6 +1874,29 @@ private:
#pragma warning(pop) /* C4800 */
#endif
template<typename... Args>
BOOST_FORCEINLINE std::pair<iterator,bool> emplace_dispatch(
std::true_type,Args&&... args
) {
using emplace_type_t = emplace_type<Args...>;
return emplace_impl(emplace_type_t(std::forward<Args>(args)...));
}
template<typename... Args>
BOOST_FORCEINLINE std::pair<iterator,bool> emplace_dispatch(
std::false_type,Args&&... args
) {
alignas(element_type)
unsigned char buf[sizeof(element_type)];
element_type* p = reinterpret_cast<element_type*>(buf);
type_policy::construct(al(),p,std::forward<Args>(args)...);
destroy_element_on_exit d{this,p};
(void)d;
return emplace_impl(type_policy::move(*p));
}
template<typename... Args>
BOOST_FORCEINLINE std::pair<iterator,bool> emplace_impl(Args&&... args)
{
@@ -1896,20 +1972,20 @@ private:
{
std::size_t num_destroyed=0;
BOOST_TRY{
for_all_elements([&,this](value_type* p){
for_all_elements([&,this](element_type* p){
nosize_transfer_element(p,new_arrays_,num_destroyed);
});
}
BOOST_CATCH(...){
if(num_destroyed){
for_all_elements_while(
[&,this](group_type* pg,unsigned int n,value_type*){
[&,this](group_type* pg,unsigned int n,element_type*){
recover_slot(pg,n);
return --num_destroyed!=0;
}
);
}
for_all_elements(new_arrays_,[this](value_type* p){
for_all_elements(new_arrays_,[this](element_type* p){
destroy_element(p);
});
delete_arrays(new_arrays_);
@@ -1920,7 +1996,7 @@ private:
/* either all moved and destroyed or all copied */
BOOST_ASSERT(num_destroyed==size()||num_destroyed==0);
if(num_destroyed!=size()){
for_all_elements([this](value_type* p){
for_all_elements([this](element_type* p){
destroy_element(p);
});
}
@@ -1955,18 +2031,19 @@ private:
}
void nosize_transfer_element(
value_type* p,const arrays_type& arrays_,std::size_t& num_destroyed)
element_type* p,const arrays_type& arrays_,std::size_t& num_destroyed)
{
nosize_transfer_element(
p,hash_for(key_from(*p)),arrays_,num_destroyed,
std::integral_constant< /* std::move_if_noexcept semantics */
bool,
std::is_nothrow_move_constructible<init_type>::value||
!std::is_copy_constructible<init_type>::value>{});
!std::is_same<element_type,value_type>::value||
!std::is_copy_constructible<element_type>::value>{});
}
void nosize_transfer_element(
value_type* p,std::size_t hash,const arrays_type& arrays_,
element_type* p,std::size_t hash,const arrays_type& arrays_,
std::size_t& num_destroyed,std::true_type /* ->move */)
{
/* Destroy p even if an an exception is thrown in the middle of move
@@ -1980,12 +2057,12 @@ private:
}
void nosize_transfer_element(
value_type* p,std::size_t hash,const arrays_type& arrays_,
element_type* p,std::size_t hash,const arrays_type& arrays_,
std::size_t& /*num_destroyed*/,std::false_type /* ->copy */)
{
nosize_unchecked_emplace_at(
arrays_,position_for(hash,arrays_),hash,
const_cast<const value_type&>(*p));
const_cast<const element_type&>(*p));
}
template<typename... Args>
@@ -2022,8 +2099,8 @@ private:
std::size_t erase_if_impl(Predicate pr)
{
std::size_t s=size();
for_all_elements([&,this](group_type* pg,unsigned int n,value_type* p){
if(pr(*p)) erase(iterator{pg,n,p});
for_all_elements([&,this](group_type* pg,unsigned int n,element_type* p){
if(pr(type_policy::value_from(*p))) erase(iterator{pg,n,p});
});
return std::size_t(s-size());
}
@@ -2038,7 +2115,7 @@ private:
static auto for_all_elements(const arrays_type& arrays_,F f)
->decltype(f(nullptr),void())
{
for_all_elements_while(arrays_,[&](value_type* p){f(p);return true;});
for_all_elements_while(arrays_,[&](element_type* p){f(p);return true;});
}
template<typename F>
@@ -2046,7 +2123,7 @@ private:
->decltype(f(nullptr,0,nullptr),void())
{
for_all_elements_while(
arrays_,[&](group_type* pg,unsigned int n,value_type* p)
arrays_,[&](group_type* pg,unsigned int n,element_type* p)
{f(pg,n,p);return true;});
}
@@ -2061,7 +2138,7 @@ private:
->decltype(f(nullptr),void())
{
for_all_elements_while(
arrays_,[&](group_type*,unsigned int,value_type* p){return f(p);});
arrays_,[&](group_type*,unsigned int,element_type* p){return f(p);});
}
template<typename F>
@@ -0,0 +1,196 @@
/* Copyright 2023 Christian Mazakas.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See https://www.boost.org/libs/unordered for library home page.
*/
#ifndef BOOST_UNORDERED_DETAIL_FOA_NODE_HANDLE_HPP
#define BOOST_UNORDERED_DETAIL_FOA_NODE_HANDLE_HPP
#include <boost/config.hpp>
#include <boost/core/allocator_access.hpp>
namespace boost{
namespace unordered{
namespace detail{
namespace foa{
template <class Iterator,class NodeType>
struct insert_return_type
{
Iterator position;
bool inserted;
NodeType node;
};
template <class T>
union opt_storage {
BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS T t_;
opt_storage(){}
~opt_storage(){}
};
template <class TypePolicy,class Allocator>
struct node_handle_base
{
protected:
using type_policy=TypePolicy;
using element_type=typename type_policy::element_type;
public:
using allocator_type = Allocator;
private:
using node_value_type=typename type_policy::value_type;
node_value_type* p_=nullptr;
BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS opt_storage<Allocator> a_;
protected:
node_value_type& element()noexcept
{
BOOST_ASSERT(!empty());
return *p_;
}
node_value_type const& element()const noexcept
{
BOOST_ASSERT(!empty());
return *p_;
}
Allocator& al()noexcept
{
BOOST_ASSERT(!empty());
return a_.t_;
}
Allocator const& al()const noexcept
{
BOOST_ASSERT(!empty());
return a_.t_;
}
void emplace(node_value_type* p,Allocator a)
{
BOOST_ASSERT(empty());
p_=p;
new(&a_.t_)Allocator(a);
}
void emplace(element_type&& x,Allocator a)
{
emplace(x.p,a);
x.p=nullptr;
}
void clear()
{
al().~Allocator();
p_=nullptr;
}
public:
constexpr node_handle_base()noexcept{}
node_handle_base(node_handle_base&& nh) noexcept
{
if (!nh.empty()){
emplace(nh.p_,nh.al());
nh.clear();
}
}
node_handle_base& operator=(node_handle_base&& nh)noexcept
{
bool const pocma=
boost::allocator_propagate_on_container_move_assignment<
Allocator>::type::value;
BOOST_ASSERT(
pocma
||empty()
||nh.empty()
||(al()==nh.al()));
if(!empty()){
type_policy::destroy(al(),p_);
if (pocma&&!nh.empty()){al()=std::move(nh.al());}
}
if(!nh.empty()){
if(empty()){new(&a_.t_)Allocator(std::move(nh.al()));}
p_=nh.p_;
nh.p_=nullptr;
nh.a_.t_.~Allocator();
}else if (!empty()){
a_.t_.~Allocator();
p_=nullptr;
}
return *this;
}
~node_handle_base()
{
if(!empty()){
type_policy::destroy(al(),p_);
a_.t_.~Allocator();
}
}
allocator_type get_allocator()const noexcept{return al();}
explicit operator bool()const noexcept{ return !empty();}
BOOST_ATTRIBUTE_NODISCARD bool empty()const noexcept{return p_==nullptr;}
void swap(node_handle_base& nh) noexcept(
boost::allocator_is_always_equal<Allocator>::type::value||
boost::allocator_propagate_on_container_swap<Allocator>::type::value)
{
using std::swap;
bool const pocs=
boost::allocator_propagate_on_container_swap<Allocator>::type::value;
if (!empty()&&!nh.empty()){
BOOST_ASSERT(pocs || al()==nh.al());
node_value_type *p=p_;
p_=nh.p_;
nh.p_=p;
if(pocs){
swap(al(),nh.al());
}
return;
}
if (empty()&&nh.empty()){return;}
if (empty()){
emplace(nh.p_,nh.al());
nh.clear();
}else{
nh.emplace(p_,al());
clear();
}
}
friend
void swap(node_handle_base& lhs,node_handle_base& rhs)
noexcept(noexcept(lhs.swap(rhs)))
{
return lhs.swap(rhs);
}
};
}
}
}
}
#endif // BOOST_UNORDERED_DETAIL_FOA_NODE_HANDLE_HPP
+30 -5
View File
@@ -32,10 +32,8 @@ namespace boost {
#pragma warning(disable : 4714) /* marked as __forceinline not inlined */
#endif
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
class unordered_flat_map
{
struct map_types
namespace detail {
template <class Key, class T> struct flat_map_types
{
using key_type = Key;
using raw_key_type = typename std::remove_const<Key>::type;
@@ -45,19 +43,46 @@ namespace boost {
using moved_type = std::pair<raw_key_type&&, raw_mapped_type&&>;
using value_type = std::pair<Key const, T>;
using element_type = value_type;
static value_type& value_from(element_type& x) { return x; }
template <class K, class V>
static raw_key_type const& extract(std::pair<K, V> const& kv)
{
return kv.first;
}
static moved_type move(value_type& x)
static moved_type move(element_type& x)
{
// TODO: we probably need to launder here
return {std::move(const_cast<raw_key_type&>(x.first)),
std::move(const_cast<raw_mapped_type&>(x.second))};
}
template <class A>
static void construct(A& al, element_type* p, moved_type&& x)
{
boost::allocator_construct(al, p, std::move(x));
}
template <class A, class... Args>
static void construct(A& al, element_type* p, Args&&... args)
{
boost::allocator_construct(al, p, std::forward<Args>(args)...);
}
template <class A> static void destroy(A& al, element_type* p) noexcept
{
boost::allocator_destroy(al, p);
}
};
} // namespace detail
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
class unordered_flat_map
{
using map_types = detail::flat_map_types<Key, T>;
using table_type = detail::foa::table<map_types, Hash, KeyEqual,
typename boost::allocator_rebind<Allocator,
+38 -5
View File
@@ -30,17 +30,50 @@ namespace boost {
#pragma warning(disable : 4714) /* marked as __forceinline not inlined */
#endif
template <class Key, class Hash, class KeyEqual, class Allocator>
class unordered_flat_set
{
struct set_types
namespace detail {
template <class Key> struct flat_set_types
{
using key_type = Key;
using init_type = Key;
using value_type = Key;
static Key const& extract(value_type const& key) { return key; }
static Key&& move(value_type& x) { return std::move(x); }
using element_type = value_type;
static Key& value_from(element_type& x) { return x; }
static element_type&& move(element_type& x) { return std::move(x); }
template <class A>
static void construct(A& al, element_type* p, element_type const& copy)
{
boost::allocator_construct(al, p, copy);
}
template <class A>
static void construct(A& al, element_type* p, Key&& x)
{
boost::allocator_construct(al, p, std::move(x));
}
template <class A, class... Args>
static void construct(A& al, element_type* p, Args&&... args)
{
boost::allocator_construct(al, p, std::forward<Args>(args)...);
}
template <class A> static void destroy(A& al, element_type* p) noexcept
{
boost::allocator_destroy(al, p);
}
};
} // namespace detail
template <class Key, class Hash, class KeyEqual, class Allocator>
class unordered_flat_set
{
using set_types = detail::flat_set_types<Key>;
using table_type = detail::foa::table<set_types, Hash, KeyEqual,
typename boost::allocator_rebind<Allocator,
@@ -0,0 +1,992 @@
// Copyright (C) 2022-2023 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_UNORDERED_NODE_MAP_HPP_INCLUDED
#define BOOST_UNORDERED_UNORDERED_NODE_MAP_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/unordered/detail/foa.hpp>
#include <boost/unordered/detail/foa/node_handle.hpp>
#include <boost/unordered/detail/type_traits.hpp>
#include <boost/unordered/unordered_node_map_fwd.hpp>
#include <boost/core/allocator_access.hpp>
#include <boost/functional/hash.hpp>
#include <boost/throw_exception.hpp>
#include <initializer_list>
#include <iterator>
#include <stdexcept>
#include <type_traits>
#include <utility>
namespace boost {
namespace unordered {
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable : 4714) /* marked as __forceinline not inlined */
#endif
namespace detail {
template <class Key, class T> struct node_map_types
{
using key_type = Key;
using mapped_type = T;
using raw_key_type = typename std::remove_const<Key>::type;
using raw_mapped_type = typename std::remove_const<T>::type;
using init_type = std::pair<raw_key_type, raw_mapped_type>;
using value_type = std::pair<Key const, T>;
using moved_type = std::pair<raw_key_type&&, raw_mapped_type&&>;
struct element_type
{
value_type* p;
/*
* we use a deleted copy constructor here so the type is no longer
* trivially copy-constructible which inhibits our memcpy
* optimizations when copying the tables
*/
element_type() = default;
element_type(element_type const&) = delete;
element_type(element_type&& rhs) noexcept
{
p = rhs.p;
rhs.p = nullptr;
}
};
static value_type& value_from(element_type const& x) { return *(x.p); }
template <class K, class V>
static raw_key_type const& extract(std::pair<K, V> const& kv)
{
return kv.first;
}
static raw_key_type const& extract(element_type const& kv)
{
return kv.p->first;
}
static element_type&& move(element_type& x) { return std::move(x); }
static moved_type move(value_type& x)
{
return {std::move(const_cast<raw_key_type&>(x.first)),
std::move(const_cast<raw_mapped_type&>(x.second))};
}
template <class A>
static void construct(A&, element_type* p, element_type&& x) noexcept
{
p->p = x.p;
x.p = nullptr;
}
template <class A>
static void construct(A& al, element_type* p, element_type const& copy)
{
construct(al, p, *copy.p);
}
template <class A, class... Args>
static void construct(A& al, element_type* p, Args&&... args)
{
p->p = boost::to_address(boost::allocator_allocate(al, 1));
BOOST_TRY
{
boost::allocator_construct(al, p->p, std::forward<Args>(args)...);
}
BOOST_CATCH(...)
{
boost::allocator_deallocate(al,
boost::pointer_traits<
typename boost::allocator_pointer<A>::type>::pointer_to(*p->p),
1);
BOOST_RETHROW
}
BOOST_CATCH_END
}
template <class A> static void destroy(A& al, value_type* p) noexcept
{
boost::allocator_destroy(al, p);
boost::allocator_deallocate(al,
boost::pointer_traits<
typename boost::allocator_pointer<A>::type>::pointer_to(*p),
1);
}
template <class A> static void destroy(A& al, element_type* p) noexcept
{
if (p->p) {
destroy(al,p->p);
}
}
};
template <class NodeMapTypes, class Allocator>
struct node_map_handle
: public detail::foa::node_handle_base<NodeMapTypes, Allocator>
{
private:
using base_type =
detail::foa::node_handle_base<NodeMapTypes, Allocator>;
using typename base_type::type_policy;
template <class Key, class T, class Hash, class Pred, class Alloc>
friend class boost::unordered::unordered_node_map;
public:
using key_type = typename NodeMapTypes::key_type;
using mapped_type = typename NodeMapTypes::mapped_type;
constexpr node_map_handle() noexcept = default;
node_map_handle(node_map_handle&& nh) noexcept = default;
node_map_handle& operator=(node_map_handle&&) noexcept = default;
key_type& key() const
{
BOOST_ASSERT(!this->empty());
return const_cast<key_type&>(this->element().first);
}
mapped_type& mapped() const
{
BOOST_ASSERT(!this->empty());
return const_cast<mapped_type&>(this->element().second);
}
};
} // namespace detail
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
class unordered_node_map
{
using map_types = detail::node_map_types<Key, T>;
using table_type = detail::foa::table<map_types, Hash, KeyEqual,
typename boost::allocator_rebind<Allocator,
std::pair<Key const, T> >::type>;
table_type table_;
template <class K, class V, class H, class KE, class A, class Pred>
typename unordered_node_map<K, V, H, KE, A>::size_type friend erase_if(
unordered_node_map<K, V, H, KE, A>& set, Pred pred);
public:
using key_type = Key;
using mapped_type = T;
using value_type = typename map_types::value_type;
using init_type = typename map_types::init_type;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using hasher = typename boost::type_identity<Hash>::type;
using key_equal = typename boost::type_identity<KeyEqual>::type;
using allocator_type = typename boost::type_identity<Allocator>::type;
using reference = value_type&;
using const_reference = value_type const&;
using pointer = typename boost::allocator_pointer<allocator_type>::type;
using const_pointer =
typename boost::allocator_const_pointer<allocator_type>::type;
using iterator = typename table_type::iterator;
using const_iterator = typename table_type::const_iterator;
using node_type = detail::node_map_handle<map_types,
typename boost::allocator_rebind<Allocator,
typename map_types::value_type>::type>;
using insert_return_type =
detail::foa::insert_return_type<iterator, node_type>;
unordered_node_map() : unordered_node_map(0) {}
explicit unordered_node_map(size_type n, hasher const& h = hasher(),
key_equal const& pred = key_equal(),
allocator_type const& a = allocator_type())
: table_(n, h, pred, a)
{
}
unordered_node_map(size_type n, allocator_type const& a)
: unordered_node_map(n, hasher(), key_equal(), a)
{
}
unordered_node_map(size_type n, hasher const& h, allocator_type const& a)
: unordered_node_map(n, h, key_equal(), a)
{
}
template <class InputIterator>
unordered_node_map(
InputIterator f, InputIterator l, allocator_type const& a)
: unordered_node_map(f, l, size_type(0), hasher(), key_equal(), a)
{
}
explicit unordered_node_map(allocator_type const& a)
: unordered_node_map(0, a)
{
}
template <class Iterator>
unordered_node_map(Iterator first, Iterator last, size_type n = 0,
hasher const& h = hasher(), key_equal const& pred = key_equal(),
allocator_type const& a = allocator_type())
: unordered_node_map(n, h, pred, a)
{
this->insert(first, last);
}
template <class Iterator>
unordered_node_map(
Iterator first, Iterator last, size_type n, allocator_type const& a)
: unordered_node_map(first, last, n, hasher(), key_equal(), a)
{
}
template <class Iterator>
unordered_node_map(Iterator first, Iterator last, size_type n,
hasher const& h, allocator_type const& a)
: unordered_node_map(first, last, n, h, key_equal(), a)
{
}
unordered_node_map(unordered_node_map const& other) : table_(other.table_)
{
}
unordered_node_map(
unordered_node_map const& other, allocator_type const& a)
: table_(other.table_, a)
{
}
unordered_node_map(unordered_node_map&& other)
noexcept(std::is_nothrow_move_constructible<hasher>::value&&
std::is_nothrow_move_constructible<key_equal>::value&&
std::is_nothrow_move_constructible<allocator_type>::value)
: table_(std::move(other.table_))
{
}
unordered_node_map(unordered_node_map&& other, allocator_type const& al)
: table_(std::move(other.table_), al)
{
}
unordered_node_map(std::initializer_list<value_type> ilist,
size_type n = 0, hasher const& h = hasher(),
key_equal const& pred = key_equal(),
allocator_type const& a = allocator_type())
: unordered_node_map(ilist.begin(), ilist.end(), n, h, pred, a)
{
}
unordered_node_map(
std::initializer_list<value_type> il, allocator_type const& a)
: unordered_node_map(il, size_type(0), hasher(), key_equal(), a)
{
}
unordered_node_map(std::initializer_list<value_type> init, size_type n,
allocator_type const& a)
: unordered_node_map(init, n, hasher(), key_equal(), a)
{
}
unordered_node_map(std::initializer_list<value_type> init, size_type n,
hasher const& h, allocator_type const& a)
: unordered_node_map(init, n, h, key_equal(), a)
{
}
~unordered_node_map() = default;
unordered_node_map& operator=(unordered_node_map const& other)
{
table_ = other.table_;
return *this;
}
unordered_node_map& operator=(unordered_node_map&& other) noexcept(
noexcept(std::declval<table_type&>() = std::declval<table_type&&>()))
{
table_ = std::move(other.table_);
return *this;
}
allocator_type get_allocator() const noexcept
{
return table_.get_allocator();
}
/// Iterators
///
iterator begin() noexcept { return table_.begin(); }
const_iterator begin() const noexcept { return table_.begin(); }
const_iterator cbegin() const noexcept { return table_.cbegin(); }
iterator end() noexcept { return table_.end(); }
const_iterator end() const noexcept { return table_.end(); }
const_iterator cend() const noexcept { return table_.cend(); }
/// Capacity
///
BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
{
return table_.empty();
}
size_type size() const noexcept { return table_.size(); }
size_type max_size() const noexcept { return table_.max_size(); }
/// Modifiers
///
void clear() noexcept { table_.clear(); }
template <class Ty>
BOOST_FORCEINLINE auto insert(Ty&& value)
-> decltype(table_.insert(std::forward<Ty>(value)))
{
return table_.insert(std::forward<Ty>(value));
}
BOOST_FORCEINLINE std::pair<iterator, bool> insert(init_type&& value)
{
return table_.insert(std::move(value));
}
template <class Ty>
BOOST_FORCEINLINE auto insert(const_iterator, Ty&& value)
-> decltype(table_.insert(std::forward<Ty>(value)).first)
{
return table_.insert(std::forward<Ty>(value)).first;
}
BOOST_FORCEINLINE iterator insert(const_iterator, init_type&& value)
{
return table_.insert(std::move(value)).first;
}
template <class InputIterator>
BOOST_FORCEINLINE void insert(InputIterator first, InputIterator last)
{
for (auto pos = first; pos != last; ++pos) {
table_.emplace(*pos);
}
}
void insert(std::initializer_list<value_type> ilist)
{
this->insert(ilist.begin(), ilist.end());
}
insert_return_type insert(node_type&& nh)
{
if (nh.empty()) {
return {end(), false, node_type{}};
}
BOOST_ASSERT(get_allocator() == nh.get_allocator());
typename map_types::element_type x;
x.p=std::addressof(nh.element());
auto itp = table_.insert(std::move(x));
if (itp.second) {
nh.clear();
return {itp.first, true, node_type{}};
} else {
return {itp.first, false, std::move(nh)};
}
}
iterator insert(const_iterator, node_type&& nh)
{
if (nh.empty()) {
return end();
}
BOOST_ASSERT(get_allocator() == nh.get_allocator());
auto itp = table_.insert(map_types::move(nh.element()));
return itp.first;
}
template <class M>
std::pair<iterator, bool> insert_or_assign(key_type const& key, M&& obj)
{
auto ibp = table_.try_emplace(key, std::forward<M>(obj));
if (ibp.second) {
return ibp;
}
ibp.first->second = std::forward<M>(obj);
return ibp;
}
template <class M>
std::pair<iterator, bool> insert_or_assign(key_type&& key, M&& obj)
{
auto ibp = table_.try_emplace(std::move(key), std::forward<M>(obj));
if (ibp.second) {
return ibp;
}
ibp.first->second = std::forward<M>(obj);
return ibp;
}
template <class K, class M>
typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
std::pair<iterator, bool> >::type
insert_or_assign(K&& k, M&& obj)
{
auto ibp = table_.try_emplace(std::forward<K>(k), std::forward<M>(obj));
if (ibp.second) {
return ibp;
}
ibp.first->second = std::forward<M>(obj);
return ibp;
}
template <class M>
iterator insert_or_assign(const_iterator, key_type const& key, M&& obj)
{
return this->insert_or_assign(key, std::forward<M>(obj)).first;
}
template <class M>
iterator insert_or_assign(const_iterator, key_type&& key, M&& obj)
{
return this->insert_or_assign(std::move(key), std::forward<M>(obj))
.first;
}
template <class K, class M>
typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
iterator>::type
insert_or_assign(const_iterator, K&& k, M&& obj)
{
return this->insert_or_assign(std::forward<K>(k), std::forward<M>(obj))
.first;
}
template <class... Args>
BOOST_FORCEINLINE std::pair<iterator, bool> emplace(Args&&... args)
{
return table_.emplace(std::forward<Args>(args)...);
}
template <class... Args>
BOOST_FORCEINLINE iterator emplace_hint(const_iterator, Args&&... args)
{
return table_.emplace(std::forward<Args>(args)...).first;
}
template <class... Args>
BOOST_FORCEINLINE std::pair<iterator, bool> try_emplace(
key_type const& key, Args&&... args)
{
return table_.try_emplace(key, std::forward<Args>(args)...);
}
template <class... Args>
BOOST_FORCEINLINE std::pair<iterator, bool> try_emplace(
key_type&& key, Args&&... args)
{
return table_.try_emplace(std::move(key), std::forward<Args>(args)...);
}
template <class K, class... Args>
BOOST_FORCEINLINE typename std::enable_if<
boost::unordered::detail::transparent_non_iterable<K,
unordered_node_map>::value,
std::pair<iterator, bool> >::type
try_emplace(K&& key, Args&&... args)
{
return table_.try_emplace(
std::forward<K>(key), std::forward<Args>(args)...);
}
template <class... Args>
BOOST_FORCEINLINE iterator try_emplace(
const_iterator, key_type const& key, Args&&... args)
{
return table_.try_emplace(key, std::forward<Args>(args)...).first;
}
template <class... Args>
BOOST_FORCEINLINE iterator try_emplace(
const_iterator, key_type&& key, Args&&... args)
{
return table_.try_emplace(std::move(key), std::forward<Args>(args)...)
.first;
}
template <class K, class... Args>
BOOST_FORCEINLINE typename std::enable_if<
boost::unordered::detail::transparent_non_iterable<K,
unordered_node_map>::value,
iterator>::type
try_emplace(const_iterator, K&& key, Args&&... args)
{
return table_
.try_emplace(std::forward<K>(key), std::forward<Args>(args)...)
.first;
}
BOOST_FORCEINLINE void erase(iterator pos) { table_.erase(pos); }
BOOST_FORCEINLINE void erase(const_iterator pos)
{
return table_.erase(pos);
}
iterator erase(const_iterator first, const_iterator last)
{
while (first != last) {
this->erase(first++);
}
return iterator{detail::foa::const_iterator_cast_tag{}, last};
}
BOOST_FORCEINLINE size_type erase(key_type const& key)
{
return table_.erase(key);
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
detail::transparent_non_iterable<K, unordered_node_map>::value,
size_type>::type
erase(K const& key)
{
return table_.erase(key);
}
void swap(unordered_node_map& rhs) noexcept(
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
{
table_.swap(rhs.table_);
}
node_type extract(const_iterator pos)
{
BOOST_ASSERT(pos != end());
node_type nh;
auto elem = table_.extract(pos);
nh.emplace(std::move(elem), get_allocator());
return nh;
}
node_type extract(key_type const& key)
{
auto pos = find(key);
return pos!=end()?extract(pos):node_type();
}
template <class K>
typename std::enable_if<
boost::unordered::detail::transparent_non_iterable<K,
unordered_node_map>::value,
node_type>::type
extract(K const& key)
{
auto pos = find(key);
return pos!=end()?extract(pos):node_type();
}
template <class H2, class P2>
void merge(
unordered_node_map<key_type, mapped_type, H2, P2, allocator_type>&
source)
{
table_.merge(source.table_);
}
template <class H2, class P2>
void merge(
unordered_node_map<key_type, mapped_type, H2, P2, allocator_type>&&
source)
{
table_.merge(std::move(source.table_));
}
/// Lookup
///
mapped_type& at(key_type const& key)
{
auto pos = table_.find(key);
if (pos != table_.end()) {
return pos->second;
}
// TODO: someday refactor this to conditionally serialize the key and
// include it in the error message
//
boost::throw_exception(
std::out_of_range("key was not found in unordered_node_map"));
}
mapped_type const& at(key_type const& key) const
{
auto pos = table_.find(key);
if (pos != table_.end()) {
return pos->second;
}
boost::throw_exception(
std::out_of_range("key was not found in unordered_node_map"));
}
template <class K>
typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
mapped_type&>::type
at(K&& key)
{
auto pos = table_.find(std::forward<K>(key));
if (pos != table_.end()) {
return pos->second;
}
boost::throw_exception(
std::out_of_range("key was not found in unordered_node_map"));
}
template <class K>
typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
mapped_type const&>::type
at(K&& key) const
{
auto pos = table_.find(std::forward<K>(key));
if (pos != table_.end()) {
return pos->second;
}
boost::throw_exception(
std::out_of_range("key was not found in unordered_node_map"));
}
BOOST_FORCEINLINE mapped_type& operator[](key_type const& key)
{
return table_.try_emplace(key).first->second;
}
BOOST_FORCEINLINE mapped_type& operator[](key_type&& key)
{
return table_.try_emplace(std::move(key)).first->second;
}
template <class K>
typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
mapped_type&>::type
operator[](K&& key)
{
return table_.try_emplace(std::forward<K>(key)).first->second;
}
BOOST_FORCEINLINE size_type count(key_type const& key) const
{
auto pos = table_.find(key);
return pos != table_.end() ? 1 : 0;
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
count(K const& key) const
{
auto pos = table_.find(key);
return pos != table_.end() ? 1 : 0;
}
BOOST_FORCEINLINE iterator find(key_type const& key)
{
return table_.find(key);
}
BOOST_FORCEINLINE const_iterator find(key_type const& key) const
{
return table_.find(key);
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
iterator>::type
find(K const& key)
{
return table_.find(key);
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
const_iterator>::type
find(K const& key) const
{
return table_.find(key);
}
BOOST_FORCEINLINE bool contains(key_type const& key) const
{
return this->find(key) != this->end();
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
bool>::type
contains(K const& key) const
{
return this->find(key) != this->end();
}
std::pair<iterator, iterator> equal_range(key_type const& key)
{
auto pos = table_.find(key);
if (pos == table_.end()) {
return {pos, pos};
}
auto next = pos;
++next;
return {pos, next};
}
std::pair<const_iterator, const_iterator> equal_range(
key_type const& key) const
{
auto pos = table_.find(key);
if (pos == table_.end()) {
return {pos, pos};
}
auto next = pos;
++next;
return {pos, next};
}
template <class K>
typename std::enable_if<
detail::are_transparent<K, hasher, key_equal>::value,
std::pair<iterator, iterator> >::type
equal_range(K const& key)
{
auto pos = table_.find(key);
if (pos == table_.end()) {
return {pos, pos};
}
auto next = pos;
++next;
return {pos, next};
}
template <class K>
typename std::enable_if<
detail::are_transparent<K, hasher, key_equal>::value,
std::pair<const_iterator, const_iterator> >::type
equal_range(K const& key) const
{
auto pos = table_.find(key);
if (pos == table_.end()) {
return {pos, pos};
}
auto next = pos;
++next;
return {pos, next};
}
/// Hash Policy
///
size_type bucket_count() const noexcept { return table_.capacity(); }
float load_factor() const noexcept { return table_.load_factor(); }
float max_load_factor() const noexcept
{
return table_.max_load_factor();
}
void max_load_factor(float) {}
size_type max_load() const noexcept { return table_.max_load(); }
void rehash(size_type n) { table_.rehash(n); }
void reserve(size_type n) { table_.reserve(n); }
/// Observers
///
hasher hash_function() const { return table_.hash_function(); }
key_equal key_eq() const { return table_.key_eq(); }
};
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
bool operator==(
unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& lhs,
unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& rhs)
{
if (&lhs == &rhs) {
return true;
}
return (lhs.size() == rhs.size()) && ([&] {
for (auto const& kvp : lhs) {
auto pos = rhs.find(kvp.first);
if ((pos == rhs.end()) || (*pos != kvp)) {
return false;
}
}
return true;
})();
}
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
bool operator!=(
unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& lhs,
unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& rhs)
{
return !(lhs == rhs);
}
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
void swap(unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& lhs,
unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& rhs)
noexcept(noexcept(lhs.swap(rhs)))
{
lhs.swap(rhs);
}
template <class Key, class T, class Hash, class KeyEqual, class Allocator,
class Pred>
typename unordered_node_map<Key, T, Hash, KeyEqual, Allocator>::size_type
erase_if(
unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& map, Pred pred)
{
return erase_if(map.table_, pred);
}
#if defined(BOOST_MSVC)
#pragma warning(pop) /* C4714 */
#endif
#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
namespace detail {
template <typename T>
using iter_key_t =
typename std::iterator_traits<T>::value_type::first_type;
template <typename T>
using iter_val_t =
typename std::iterator_traits<T>::value_type::second_type;
template <typename T>
using iter_to_alloc_t =
typename std::pair<iter_key_t<T> const, iter_val_t<T> >;
} // namespace detail
template <class InputIterator,
class Hash =
boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
class Pred =
std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
class Allocator = std::allocator<
boost::unordered::detail::iter_to_alloc_t<InputIterator> >,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_map(InputIterator, InputIterator,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
boost::unordered::detail::iter_val_t<InputIterator>, Hash, Pred,
Allocator>;
template <class Key, class T,
class Hash = boost::hash<boost::remove_const_t<Key> >,
class Pred = std::equal_to<boost::remove_const_t<Key> >,
class Allocator = std::allocator<std::pair<const Key, T> >,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_map(std::initializer_list<std::pair<Key, T> >,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_node_map<boost::remove_const_t<Key>, T, Hash, Pred,
Allocator>;
template <class InputIterator, class Allocator,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_map(InputIterator, InputIterator, std::size_t, Allocator)
-> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
boost::unordered::detail::iter_val_t<InputIterator>,
boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
Allocator>;
template <class InputIterator, class Allocator,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_map(InputIterator, InputIterator, Allocator)
-> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
boost::unordered::detail::iter_val_t<InputIterator>,
boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
Allocator>;
template <class InputIterator, class Hash, class Allocator,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_map(
InputIterator, InputIterator, std::size_t, Hash, Allocator)
-> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
boost::unordered::detail::iter_val_t<InputIterator>, Hash,
std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
Allocator>;
template <class Key, class T, class Allocator,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
Allocator) -> unordered_node_map<boost::remove_const_t<Key>, T,
boost::hash<boost::remove_const_t<Key> >,
std::equal_to<boost::remove_const_t<Key> >, Allocator>;
template <class Key, class T, class Allocator,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_map(std::initializer_list<std::pair<Key, T> >, Allocator)
-> unordered_node_map<boost::remove_const_t<Key>, T,
boost::hash<boost::remove_const_t<Key> >,
std::equal_to<boost::remove_const_t<Key> >, Allocator>;
template <class Key, class T, class Hash, class Allocator,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
Hash, Allocator) -> unordered_node_map<boost::remove_const_t<Key>, T,
Hash, std::equal_to<boost::remove_const_t<Key> >, Allocator>;
#endif
} // namespace unordered
} // namespace boost
#endif
@@ -0,0 +1,49 @@
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_NODE_MAP_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_NODE_MAP_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/functional/hash_fwd.hpp>
#include <boost/unordered/detail/fwd.hpp>
#include <functional>
#include <memory>
namespace boost {
namespace unordered {
template <class Key, class T, class Hash = boost::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<const Key, T> > >
class unordered_node_map;
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
bool operator==(
unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& lhs,
unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& rhs);
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
bool operator!=(
unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& lhs,
unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& rhs);
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
void swap(unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& lhs,
unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& rhs)
noexcept(noexcept(lhs.swap(rhs)));
} // namespace unordered
using boost::unordered::unordered_node_map;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
} // namespace boost
#endif
@@ -0,0 +1,772 @@
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_UNORDERED_NODE_SET_HPP_INCLUDED
#define BOOST_UNORDERED_UNORDERED_NODE_SET_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/unordered/detail/foa.hpp>
#include <boost/unordered/detail/foa/node_handle.hpp>
#include <boost/unordered/detail/type_traits.hpp>
#include <boost/unordered/unordered_node_set_fwd.hpp>
#include <boost/core/allocator_access.hpp>
#include <boost/functional/hash.hpp>
#include <boost/throw_exception.hpp>
#include <initializer_list>
#include <iterator>
#include <type_traits>
#include <utility>
namespace boost {
namespace unordered {
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable : 4714) /* marked as __forceinline not inlined */
#endif
namespace detail {
template <class Key> struct node_set_types
{
using key_type = Key;
using init_type = Key;
using value_type = Key;
static Key const& extract(value_type const& key) { return key; }
struct element_type
{
value_type* p;
/*
* we use a deleted copy constructor here so the type is no longer
* trivially copy-constructible which inhibits our memcpy
* optimizations when copying the tables
*/
element_type() = default;
element_type(element_type const&) = delete;
element_type(element_type&& rhs) noexcept
{
p = rhs.p;
rhs.p = nullptr;
}
};
static value_type& value_from(element_type const& x) { return *x.p; }
static Key const& extract(element_type const& k) { return *k.p; }
static element_type&& move(element_type& x) { return std::move(x); }
static value_type&& move(value_type& x) { return std::move(x); }
template <class A>
static void construct(A& al, element_type* p, element_type const& copy)
{
construct(al, p, *copy.p);
}
template <typename Allocator>
static void construct(
Allocator&, element_type* p, element_type&& x) noexcept
{
p->p = x.p;
x.p = nullptr;
}
template <class A, class... Args>
static void construct(A& al, element_type* p, Args&&... args)
{
p->p = boost::to_address(boost::allocator_allocate(al, 1));
BOOST_TRY
{
boost::allocator_construct(al, p->p, std::forward<Args>(args)...);
}
BOOST_CATCH(...)
{
boost::allocator_deallocate(al,
boost::pointer_traits<
typename boost::allocator_pointer<A>::type>::pointer_to(*p->p),
1);
BOOST_RETHROW
}
BOOST_CATCH_END
}
template <class A> static void destroy(A& al, value_type* p) noexcept
{
boost::allocator_destroy(al, p);
boost::allocator_deallocate(al,
boost::pointer_traits<
typename boost::allocator_pointer<A>::type>::pointer_to(*p),
1);
}
template <class A> static void destroy(A& al, element_type* p) noexcept
{
if (p->p) {
destroy(al, p->p);
}
}
};
template <class NodeSetTypes, class Allocator>
struct node_set_handle
: public detail::foa::node_handle_base<NodeSetTypes, Allocator>
{
private:
using base_type =
detail::foa::node_handle_base<NodeSetTypes, Allocator>;
using typename base_type::type_policy;
template <class Key, class Hash, class Pred, class Alloc>
friend class boost::unordered::unordered_node_set;
public:
using value_type = typename NodeSetTypes::value_type;
constexpr node_set_handle() noexcept = default;
node_set_handle(node_set_handle&& nh) noexcept = default;
node_set_handle& operator=(node_set_handle&&) noexcept = default;
value_type& value() const
{
BOOST_ASSERT(!this->empty());
return const_cast<value_type&>(this->element());
}
};
} // namespace detail
template <class Key, class Hash, class KeyEqual, class Allocator>
class unordered_node_set
{
using set_types = detail::node_set_types<Key>;
using table_type = detail::foa::table<set_types, Hash, KeyEqual,
typename boost::allocator_rebind<Allocator,
typename set_types::value_type>::type>;
table_type table_;
template <class K, class H, class KE, class A, class Pred>
typename unordered_node_set<K, H, KE, A>::size_type friend erase_if(
unordered_node_set<K, H, KE, A>& set, Pred pred);
public:
using key_type = Key;
using value_type = typename set_types::value_type;
using init_type = typename set_types::init_type;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using hasher = Hash;
using key_equal = KeyEqual;
using allocator_type = Allocator;
using reference = value_type&;
using const_reference = value_type const&;
using pointer = typename boost::allocator_pointer<allocator_type>::type;
using const_pointer =
typename boost::allocator_const_pointer<allocator_type>::type;
using iterator = typename table_type::iterator;
using const_iterator = typename table_type::const_iterator;
using node_type = detail::node_set_handle<set_types,
typename boost::allocator_rebind<Allocator,
typename set_types::value_type>::type>;
using insert_return_type =
detail::foa::insert_return_type<iterator, node_type>;
unordered_node_set() : unordered_node_set(0) {}
explicit unordered_node_set(size_type n, hasher const& h = hasher(),
key_equal const& pred = key_equal(),
allocator_type const& a = allocator_type())
: table_(n, h, pred, a)
{
}
unordered_node_set(size_type n, allocator_type const& a)
: unordered_node_set(n, hasher(), key_equal(), a)
{
}
unordered_node_set(size_type n, hasher const& h, allocator_type const& a)
: unordered_node_set(n, h, key_equal(), a)
{
}
template <class InputIterator>
unordered_node_set(
InputIterator f, InputIterator l, allocator_type const& a)
: unordered_node_set(f, l, size_type(0), hasher(), key_equal(), a)
{
}
explicit unordered_node_set(allocator_type const& a)
: unordered_node_set(0, a)
{
}
template <class Iterator>
unordered_node_set(Iterator first, Iterator last, size_type n = 0,
hasher const& h = hasher(), key_equal const& pred = key_equal(),
allocator_type const& a = allocator_type())
: unordered_node_set(n, h, pred, a)
{
this->insert(first, last);
}
template <class InputIt>
unordered_node_set(
InputIt first, InputIt last, size_type n, allocator_type const& a)
: unordered_node_set(first, last, n, hasher(), key_equal(), a)
{
}
template <class Iterator>
unordered_node_set(Iterator first, Iterator last, size_type n,
hasher const& h, allocator_type const& a)
: unordered_node_set(first, last, n, h, key_equal(), a)
{
}
unordered_node_set(unordered_node_set const& other) : table_(other.table_)
{
}
unordered_node_set(
unordered_node_set const& other, allocator_type const& a)
: table_(other.table_, a)
{
}
unordered_node_set(unordered_node_set&& other)
noexcept(std::is_nothrow_move_constructible<hasher>::value&&
std::is_nothrow_move_constructible<key_equal>::value&&
std::is_nothrow_move_constructible<allocator_type>::value)
: table_(std::move(other.table_))
{
}
unordered_node_set(unordered_node_set&& other, allocator_type const& al)
: table_(std::move(other.table_), al)
{
}
unordered_node_set(std::initializer_list<value_type> ilist,
size_type n = 0, hasher const& h = hasher(),
key_equal const& pred = key_equal(),
allocator_type const& a = allocator_type())
: unordered_node_set(ilist.begin(), ilist.end(), n, h, pred, a)
{
}
unordered_node_set(
std::initializer_list<value_type> il, allocator_type const& a)
: unordered_node_set(il, size_type(0), hasher(), key_equal(), a)
{
}
unordered_node_set(std::initializer_list<value_type> init, size_type n,
allocator_type const& a)
: unordered_node_set(init, n, hasher(), key_equal(), a)
{
}
unordered_node_set(std::initializer_list<value_type> init, size_type n,
hasher const& h, allocator_type const& a)
: unordered_node_set(init, n, h, key_equal(), a)
{
}
~unordered_node_set() = default;
unordered_node_set& operator=(unordered_node_set const& other)
{
table_ = other.table_;
return *this;
}
unordered_node_set& operator=(unordered_node_set&& other) noexcept(
noexcept(std::declval<table_type&>() = std::declval<table_type&&>()))
{
table_ = std::move(other.table_);
return *this;
}
allocator_type get_allocator() const noexcept
{
return table_.get_allocator();
}
/// Iterators
///
iterator begin() noexcept { return table_.begin(); }
const_iterator begin() const noexcept { return table_.begin(); }
const_iterator cbegin() const noexcept { return table_.cbegin(); }
iterator end() noexcept { return table_.end(); }
const_iterator end() const noexcept { return table_.end(); }
const_iterator cend() const noexcept { return table_.cend(); }
/// Capacity
///
BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
{
return table_.empty();
}
size_type size() const noexcept { return table_.size(); }
size_type max_size() const noexcept { return table_.max_size(); }
/// Modifiers
///
void clear() noexcept { table_.clear(); }
BOOST_FORCEINLINE std::pair<iterator, bool> insert(
value_type const& value)
{
return table_.insert(value);
}
BOOST_FORCEINLINE std::pair<iterator, bool> insert(value_type&& value)
{
return table_.insert(std::move(value));
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
detail::transparent_non_iterable<K, unordered_node_set>::value,
std::pair<iterator, bool> >::type
insert(K&& k)
{
return table_.try_emplace(std::forward<K>(k));
}
BOOST_FORCEINLINE iterator insert(const_iterator, value_type const& value)
{
return table_.insert(value).first;
}
BOOST_FORCEINLINE iterator insert(const_iterator, value_type&& value)
{
return table_.insert(std::move(value)).first;
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
detail::transparent_non_iterable<K, unordered_node_set>::value,
iterator>::type
insert(const_iterator, K&& k)
{
return table_.try_emplace(std::forward<K>(k)).first;
}
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
{
for (auto pos = first; pos != last; ++pos) {
table_.emplace(*pos);
}
}
void insert(std::initializer_list<value_type> ilist)
{
this->insert(ilist.begin(), ilist.end());
}
insert_return_type insert(node_type&& nh)
{
if (nh.empty()) {
return {end(), false, node_type{}};
}
BOOST_ASSERT(get_allocator() == nh.get_allocator());
typename set_types::element_type x;
x.p=std::addressof(nh.element());
auto itp = table_.insert(std::move(x));
if (itp.second) {
nh.clear();
return {itp.first, true, node_type{}};
} else {
return {itp.first, false, std::move(nh)};
}
}
iterator insert(const_iterator, node_type&& nh)
{
if (nh.empty()) {
return end();
}
BOOST_ASSERT(get_allocator() == nh.get_allocator());
auto itp = table_.insert(set_types::move(nh.element()));
return itp.first;
}
template <class... Args>
BOOST_FORCEINLINE std::pair<iterator, bool> emplace(Args&&... args)
{
return table_.emplace(std::forward<Args>(args)...);
}
template <class... Args>
BOOST_FORCEINLINE iterator emplace_hint(const_iterator, Args&&... args)
{
return table_.emplace(std::forward<Args>(args)...).first;
}
BOOST_FORCEINLINE void erase(const_iterator pos)
{
return table_.erase(pos);
}
iterator erase(const_iterator first, const_iterator last)
{
while (first != last) {
this->erase(first++);
}
return iterator{detail::foa::const_iterator_cast_tag{}, last};
}
BOOST_FORCEINLINE size_type erase(key_type const& key)
{
return table_.erase(key);
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
detail::transparent_non_iterable<K, unordered_node_set>::value,
size_type>::type
erase(K const& key)
{
return table_.erase(key);
}
void swap(unordered_node_set& rhs) noexcept(
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
{
table_.swap(rhs.table_);
}
node_type extract(const_iterator pos)
{
BOOST_ASSERT(pos != end());
node_type nh;
auto elem = table_.extract(pos);
nh.emplace(std::move(elem), get_allocator());
return nh;
}
node_type extract(key_type const& key)
{
auto pos = find(key);
return pos!=end()?extract(pos):node_type();
}
template <class K>
typename std::enable_if<
boost::unordered::detail::transparent_non_iterable<K,
unordered_node_set>::value,
node_type>::type
extract(K const& key)
{
auto pos = find(key);
return pos!=end()?extract(pos):node_type();
}
template <class H2, class P2>
void merge(unordered_node_set<key_type, H2, P2, allocator_type>& source)
{
table_.merge(source.table_);
}
template <class H2, class P2>
void merge(unordered_node_set<key_type, H2, P2, allocator_type>&& source)
{
table_.merge(std::move(source.table_));
}
/// Lookup
///
BOOST_FORCEINLINE size_type count(key_type const& key) const
{
auto pos = table_.find(key);
return pos != table_.end() ? 1 : 0;
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
count(K const& key) const
{
auto pos = table_.find(key);
return pos != table_.end() ? 1 : 0;
}
BOOST_FORCEINLINE iterator find(key_type const& key)
{
return table_.find(key);
}
BOOST_FORCEINLINE const_iterator find(key_type const& key) const
{
return table_.find(key);
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
iterator>::type
find(K const& key)
{
return table_.find(key);
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
const_iterator>::type
find(K const& key) const
{
return table_.find(key);
}
BOOST_FORCEINLINE bool contains(key_type const& key) const
{
return this->find(key) != this->end();
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
bool>::type
contains(K const& key) const
{
return this->find(key) != this->end();
}
std::pair<iterator, iterator> equal_range(key_type const& key)
{
auto pos = table_.find(key);
if (pos == table_.end()) {
return {pos, pos};
}
auto next = pos;
++next;
return {pos, next};
}
std::pair<const_iterator, const_iterator> equal_range(
key_type const& key) const
{
auto pos = table_.find(key);
if (pos == table_.end()) {
return {pos, pos};
}
auto next = pos;
++next;
return {pos, next};
}
template <class K>
typename std::enable_if<
detail::are_transparent<K, hasher, key_equal>::value,
std::pair<iterator, iterator> >::type
equal_range(K const& key)
{
auto pos = table_.find(key);
if (pos == table_.end()) {
return {pos, pos};
}
auto next = pos;
++next;
return {pos, next};
}
template <class K>
typename std::enable_if<
detail::are_transparent<K, hasher, key_equal>::value,
std::pair<const_iterator, const_iterator> >::type
equal_range(K const& key) const
{
auto pos = table_.find(key);
if (pos == table_.end()) {
return {pos, pos};
}
auto next = pos;
++next;
return {pos, next};
}
/// Hash Policy
///
size_type bucket_count() const noexcept { return table_.capacity(); }
float load_factor() const noexcept { return table_.load_factor(); }
float max_load_factor() const noexcept
{
return table_.max_load_factor();
}
void max_load_factor(float) {}
size_type max_load() const noexcept { return table_.max_load(); }
void rehash(size_type n) { table_.rehash(n); }
void reserve(size_type n) { table_.reserve(n); }
/// Observers
///
hasher hash_function() const { return table_.hash_function(); }
key_equal key_eq() const { return table_.key_eq(); }
};
template <class Key, class Hash, class KeyEqual, class Allocator>
bool operator==(
unordered_node_set<Key, Hash, KeyEqual, Allocator> const& lhs,
unordered_node_set<Key, Hash, KeyEqual, Allocator> const& rhs)
{
if (&lhs == &rhs) {
return true;
}
return (lhs.size() == rhs.size()) && ([&] {
for (auto const& key : lhs) {
auto pos = rhs.find(key);
if ((pos == rhs.end()) || (key != *pos)) {
return false;
}
}
return true;
})();
}
template <class Key, class Hash, class KeyEqual, class Allocator>
bool operator!=(
unordered_node_set<Key, Hash, KeyEqual, Allocator> const& lhs,
unordered_node_set<Key, Hash, KeyEqual, Allocator> const& rhs)
{
return !(lhs == rhs);
}
template <class Key, class Hash, class KeyEqual, class Allocator>
void swap(unordered_node_set<Key, Hash, KeyEqual, Allocator>& lhs,
unordered_node_set<Key, Hash, KeyEqual, Allocator>& rhs)
noexcept(noexcept(lhs.swap(rhs)))
{
lhs.swap(rhs);
}
template <class Key, class Hash, class KeyEqual, class Allocator,
class Pred>
typename unordered_node_set<Key, Hash, KeyEqual, Allocator>::size_type
erase_if(unordered_node_set<Key, Hash, KeyEqual, Allocator>& set, Pred pred)
{
return erase_if(set.table_, pred);
}
#if defined(BOOST_MSVC)
#pragma warning(pop) /* C4714 */
#endif
#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
template <class InputIterator,
class Hash =
boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
class Pred =
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
class Allocator = std::allocator<
typename std::iterator_traits<InputIterator>::value_type>,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(InputIterator, InputIterator,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_node_set<
typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
Allocator>;
template <class T, class Hash = boost::hash<T>,
class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(std::initializer_list<T>,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_node_set<T, Hash, Pred, Allocator>;
template <class InputIterator, class Allocator,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(InputIterator, InputIterator, std::size_t, Allocator)
-> unordered_node_set<
typename std::iterator_traits<InputIterator>::value_type,
boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
Allocator>;
template <class InputIterator, class Hash, class Allocator,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(
InputIterator, InputIterator, std::size_t, Hash, Allocator)
-> unordered_node_set<
typename std::iterator_traits<InputIterator>::value_type, Hash,
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
Allocator>;
template <class T, class Allocator,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(std::initializer_list<T>, std::size_t, Allocator)
-> unordered_node_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
template <class T, class Hash, class Allocator,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(std::initializer_list<T>, std::size_t, Hash, Allocator)
-> unordered_node_set<T, Hash, std::equal_to<T>, Allocator>;
template <class InputIterator, class Allocator,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(InputIterator, InputIterator, Allocator)
-> unordered_node_set<
typename std::iterator_traits<InputIterator>::value_type,
boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
Allocator>;
template <class T, class Allocator,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(std::initializer_list<T>, Allocator)
-> unordered_node_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
#endif
} // namespace unordered
} // namespace boost
#endif
@@ -0,0 +1,49 @@
// Copyright (C) 2023 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_NODE_SET_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_NODE_SET_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/functional/hash_fwd.hpp>
#include <boost/unordered/detail/fwd.hpp>
#include <functional>
#include <memory>
namespace boost {
namespace unordered {
template <class Key, class Hash = boost::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<Key> >
class unordered_node_set;
template <class Key, class Hash, class KeyEqual, class Allocator>
bool operator==(
unordered_node_set<Key, Hash, KeyEqual, Allocator> const& lhs,
unordered_node_set<Key, Hash, KeyEqual, Allocator> const& rhs);
template <class Key, class Hash, class KeyEqual, class Allocator>
bool operator!=(
unordered_node_set<Key, Hash, KeyEqual, Allocator> const& lhs,
unordered_node_set<Key, Hash, KeyEqual, Allocator> const& rhs);
template <class Key, class Hash, class KeyEqual, class Allocator>
void swap(unordered_node_set<Key, Hash, KeyEqual, Allocator>& lhs,
unordered_node_set<Key, Hash, KeyEqual, Allocator>& rhs)
noexcept(noexcept(lhs.swap(rhs)));
} // namespace unordered
using boost::unordered::unordered_node_set;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
} // namespace boost
#endif
+5 -1
View File
@@ -1,6 +1,6 @@
# Copyright 2006-2008 Daniel James.
# Copyright 2022 Christian Mazakas
# Copyright 2022-2023 Christian Mazakas
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -26,6 +26,7 @@ project
<toolset>gcc-4.4:<cxxflags>-Wno-strict-aliasing
<toolset>gcc-4.4:<cxxflags>-fno-deduce-init-list
<toolset>clang-14:<cxxflags>-Wunused-template
<toolset>gcc:<warnings-as-errors>on
<toolset>clang:<warnings-as-errors>on
@@ -94,6 +95,7 @@ run exception/erase_exception_tests.cpp ;
run exception/rehash_exception_tests.cpp ;
run exception/swap_exception_tests.cpp : : : <define>BOOST_UNORDERED_SWAP_METHOD=2 ;
run exception/merge_exception_tests.cpp ;
run exception/less_tests.cpp ;
run unordered/narrow_cast_tests.cpp ;
run quick.cpp ;
@@ -140,6 +142,8 @@ build_foa erase_if ;
build_foa scary_tests ;
build_foa init_type_insert_tests ;
build_foa max_load_tests ;
build_foa extract_tests ;
build_foa node_handle_tests ;
run unordered/hash_is_avalanching_test.cpp ;
+18 -2
View File
@@ -25,8 +25,24 @@ typedef boost::unordered_flat_set<
test::exception::allocator<test::exception::object> >
test_pair_set;
#define CONTAINER_SEQ (test_set)(test_map)
#define CONTAINER_PAIR_SEQ (test_pair_set)(test_map)
typedef boost::unordered_node_set<test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator<test::exception::object> >
test_node_set;
typedef boost::unordered_node_map<test::exception::object,
test::exception::object, test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >
test_node_map;
typedef boost::unordered_node_set<
std::pair<test::exception::object, test::exception::object>,
test::exception::hash, test::exception::equal_to,
test::exception::allocator<test::exception::object> >
test_pair_node_set;
#define CONTAINER_SEQ (test_set)(test_map)(test_node_set)(test_node_map)
#define CONTAINER_PAIR_SEQ (test_pair_set)(test_map)(test_pair_node_set)(test_node_map)
#else
typedef boost::unordered_set<test::exception::object, test::exception::hash,
test::exception::equal_to,
+25 -7
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "./containers.hpp"
@@ -229,10 +229,12 @@ using test::generate_collisions;
#ifdef BOOST_UNORDERED_FOA_TESTS
test_set* test_set_;
test_map* test_map_;
test_node_set* test_node_set_;
test_node_map* test_node_map_;
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_set_)(test_map_))
((test_set_)(test_map_)(test_node_set_)(test_node_map_))
((insert_lvalue)(insert_lvalue_begin)(insert_lvalue_end)
(insert_lvalue_pos)(insert_single_item_range)
(emplace_lvalue)(emplace_lvalue_begin)(emplace_lvalue_end)
@@ -242,7 +244,7 @@ UNORDERED_TEST(insert_exception_test,
)
UNORDERED_TEST(insert_rehash_exception_test,
((test_set_)(test_map_))
((test_set_)(test_map_)(test_node_set_)(test_node_map_))
((insert_lvalue)(insert_lvalue_begin)(insert_lvalue_end)
(insert_lvalue_pos)(insert_single_item_range)
(emplace_lvalue)(emplace_lvalue_begin)(emplace_lvalue_end)
@@ -314,15 +316,16 @@ struct pair_emplace2_type : inserter_base
#ifdef BOOST_UNORDERED_FOA_TESTS
test_pair_set* test_pair_set_;
test_pair_node_set* test_pair_node_set_;
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_pair_set_)(test_map_))
((test_pair_set_)(test_map_)(test_pair_node_set_)(test_node_map_))
((pair_emplace)(pair_emplace2))
((default_generator)(limited_range)(generate_collisions))
)
UNORDERED_TEST(insert_rehash_exception_test,
((test_pair_set_)(test_map_))
((test_pair_set_)(test_map_)(test_pair_node_set_)(test_node_map_))
((pair_emplace)(pair_emplace2))
((default_generator)(limited_range)(generate_collisions))
)
@@ -399,6 +402,20 @@ struct map_insert_or_assign_type : map_inserter_base
}
} map_insert_or_assign;
#ifdef BOOST_UNORDERED_FOA_TESTS
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_map_)(test_node_map_))
((try_emplace)(try_emplace2)(map_insert_operator)(map_insert_or_assign))
((default_generator)(limited_range)(generate_collisions))
)
UNORDERED_TEST(insert_rehash_exception_test,
((test_map_)(test_node_map_))
((try_emplace)(try_emplace2)(map_insert_operator)(map_insert_or_assign))
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
#else
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_map_))
@@ -411,6 +428,7 @@ UNORDERED_TEST(insert_rehash_exception_test,
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
#endif
// Range insert tests
@@ -459,12 +477,12 @@ void insert_range_rehash_exception_test(T*, test::random_generator gen)
#ifdef BOOST_UNORDERED_FOA_TESTS
// clang-format off
UNORDERED_TEST(insert_range_exception_test,
((test_set_)(test_map_))
((test_set_)(test_map_)(test_node_set_)(test_node_map_))
((default_generator)(limited_range)(generate_collisions))
)
UNORDERED_TEST(insert_range_rehash_exception_test,
((test_set_)(test_map_))
((test_set_)(test_map_)(test_node_set_)(test_node_map_))
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
+50
View File
@@ -0,0 +1,50 @@
// Copyright 2023 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "./containers.hpp"
#include "../helpers/helpers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/strong.hpp"
#include "../helpers/tracker.hpp"
#include <vector>
UNORDERED_AUTO_TEST (less_osx_regression) {
DISABLE_EXCEPTIONS;
typedef test_pair_set::value_type value_type;
typedef test::exception::object object;
std::vector<value_type> v;
v.push_back(value_type(object(12, 98), object(88, 13)));
v.push_back(value_type(object(24, 71), object(62, 84)));
v.push_back(value_type(object(30, 0), object(5, 73)));
v.push_back(value_type(object(34, 64), object(79, 58)));
v.push_back(value_type(object(36, 95), object(64, 23)));
v.push_back(value_type(object(42, 89), object(68, 44)));
v.push_back(value_type(object(42, 26), object(93, 64)));
v.push_back(value_type(object(86, 86), object(16, 62)));
v.push_back(value_type(object(86, 86), object(75, 23)));
v.push_back(value_type(object(92, 37), object(41, 90)));
BOOST_TEST_EQ(v.size(), 10u);
std::set<value_type, test::exception::less> s;
s.insert(v.begin(), v.end());
BOOST_TEST_EQ(s.size(), v.size());
test::ordered<test_pair_set> tracker;
test_pair_set x;
for (std::vector<value_type>::iterator it = v.begin(); it != v.end();
++it) {
x.insert(*it);
}
tracker.insert(v.begin(), v.end());
tracker.compare(x);
}
RUN_TESTS()
+41 -1
View File
@@ -1,6 +1,6 @@
// Copyright 2017-2018 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -64,6 +64,12 @@ boost::unordered_flat_set<test::exception::object, test::exception::hash,
boost::unordered_flat_map<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >* test_map_;
boost::unordered_node_set<test::exception::object, test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> >* test_node_set_;
boost::unordered_node_map<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >* test_node_map_;
// clang-format off
UNORDERED_MULTI_TEST(set_merge, merge_exception_test,
@@ -99,6 +105,40 @@ UNORDERED_MULTI_TEST(map_merge_collisions, merge_exception_test,
((generate_collisions))
((generate_collisions))
)
UNORDERED_MULTI_TEST(node_set_merge, merge_exception_test,
((test_node_set_))
((test_node_set_))
(/* (0x0000)(0x6400) */(0x0064)/* (0x0a64)(0x3232) */)
((0x0000)(0x0001)(0x0102))
((default_generator)(limited_range))
((default_generator)(limited_range))
)
UNORDERED_MULTI_TEST(node_map_merge, merge_exception_test,
((test_node_map_))
((test_node_map_))
((0x0000)(0x6400)(0x0064)(0x0a64)(0x3232))
((0x0101)(0x0200)(0x0201))
((default_generator)(limited_range))
((default_generator)(limited_range))
)
// Run fewer generate_collisions tests, as they're slow.
UNORDERED_MULTI_TEST(node_set_merge_collisions, merge_exception_test,
((test_node_set_))
((test_node_set_))
((0x0a0a))
((0x0202)(0x0100)(0x0201))
((generate_collisions))
((generate_collisions))
)
UNORDERED_MULTI_TEST(node_map_merge_collisions, merge_exception_test,
((test_node_map_))
((test_node_map_))
((0x0a0a))
((0x0000)(0x0002)(0x0102))
((generate_collisions))
((generate_collisions))
)
// clang-format on
#else
boost::unordered_set<test::exception::object, test::exception::hash,
test::exception::equal_to,
+7 -1
View File
@@ -247,8 +247,14 @@ using unordered_flat_set = boost::unordered_flat_set<int, boost::hash<int>,
std::equal_to<int>, test::allocator1<int> >;
using unordered_flat_map = boost::unordered_flat_map<int, int, boost::hash<int>,
std::equal_to<int>, test::allocator1<std::pair<int const, int> > >;
using unordered_node_set = boost::unordered_node_set<int, boost::hash<int>,
std::equal_to<int>, test::allocator1<int> >;
using unordered_node_map = boost::unordered_node_map<int, int, boost::hash<int>,
std::equal_to<int>, test::allocator1<std::pair<int const, int> > >;
#define SWAP_CONTAINER_SEQ (unordered_flat_set)(unordered_flat_map)
#define SWAP_CONTAINER_SEQ \
(unordered_flat_set)(unordered_flat_map) \
(unordered_node_set)(unordered_node_map)
#else
+2 -3
View File
@@ -42,9 +42,8 @@ namespace test {
value_list values2(x2.begin(), x2.end());
values1.sort();
values2.sort();
BOOST_TEST(values1.size() == values2.size() &&
test::equal(values1.begin(), values1.end(), values2.begin(),
test::equivalent));
BOOST_TEST_ALL_WITH(values1.begin(), values1.end(), values2.begin(),
values2.end(), test::equivalent);
}
template <class X1, class X2, class T>
+2
View File
@@ -11,6 +11,8 @@
#ifdef BOOST_UNORDERED_FOA_TESTS
#include <boost/unordered/unordered_flat_set.hpp>
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/unordered/unordered_node_map.hpp>
#include <boost/unordered/unordered_node_set.hpp>
#include <boost/unordered/detail/implementation.hpp>
#else
#include <boost/unordered_set.hpp>
+1 -1
View File
@@ -262,7 +262,7 @@ namespace test {
if (less_impl(x1.first, x2.first)) {
return true;
}
if (!less_impl(x1.first, x2.first)) {
if (less_impl(x2.first, x1.first)) {
return false;
}
return less_impl(x1.second, x2.second);
+50 -3
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -209,40 +209,75 @@ namespace assign_tests {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, std::allocator<test::object> >* test_node_map_std_alloc;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_map;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_node_map;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_set_prop_assign;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_node_set_prop_assign;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_map_prop_assign;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_node_map_prop_assign;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_set_no_prop_assign;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_node_set_no_prop_assign;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_map_no_prop_assign;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_node_map_no_prop_assign;
UNORDERED_AUTO_TEST (check_traits) {
BOOST_TEST(!is_propagate(test_set));
BOOST_TEST(is_propagate(test_set_prop_assign));
BOOST_TEST(!is_propagate(test_set_no_prop_assign));
BOOST_TEST(!is_propagate(test_node_set));
BOOST_TEST(is_propagate(test_node_set_prop_assign));
BOOST_TEST(!is_propagate(test_node_set_no_prop_assign));
}
UNORDERED_TEST(assign_tests1,
((test_map_std_alloc)(test_set)(test_map)(test_set_prop_assign)(test_map_prop_assign)(test_set_no_prop_assign)(test_map_no_prop_assign))(
((test_map_std_alloc)(test_node_map_std_alloc)
(test_set)(test_node_set)
(test_map)(test_node_map)
(test_set_prop_assign)(test_node_set_prop_assign)
(test_map_prop_assign)(test_node_map_prop_assign)
(test_set_no_prop_assign)(test_node_set_no_prop_assign)
(test_map_no_prop_assign)(test_node_map_no_prop_assign))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(assign_tests2,
((test_set)(test_map)(test_set_prop_assign)(test_map_prop_assign)(test_set_no_prop_assign)(test_map_no_prop_assign))(
((test_set)(test_node_set)
(test_map)(test_node_map)
(test_set_prop_assign)(test_node_set_prop_assign)
(test_map_prop_assign)(test_node_map_prop_assign)
(test_set_no_prop_assign)(test_node_set_no_prop_assign)
(test_map_no_prop_assign)(test_node_map_no_prop_assign))(
(default_generator)(generate_collisions)(limited_range)))
#else
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
@@ -315,6 +350,12 @@ namespace assign_tests {
std::initializer_list<std::pair<int const, int> > init;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<int, int> x1;
boost::unordered_node_map<int, int> x2;
x2[25] = 3;
x2[16] = 10;
BOOST_TEST(!x2.empty());
x2 = init;
BOOST_TEST(x2.empty());
#else
boost::unordered_map<int, int> x1;
#endif
@@ -333,6 +374,12 @@ namespace assign_tests {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> x;
boost::unordered_node_set<int> y;
y.insert(10);
y.insert(20);
y = {1, 2, -10};
BOOST_TEST(y.find(10) == y.end());
BOOST_TEST(y.find(-10) != y.end());
#else
boost::unordered_set<int> x;
#endif
+21 -10
View File
@@ -1,6 +1,6 @@
// Copyright 2007-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -11,16 +11,12 @@
namespace at_tests {
UNORDERED_AUTO_TEST (at_tests) {
template <class X> static void at_tests(X*)
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<std::string, int> x;
boost::unordered_flat_map<std::string, int> const& x_const(x);
#else
boost::unordered_map<std::string, int> x;
boost::unordered_map<std::string, int> const& x_const(x);
#endif
X x;
X const& x_const(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check empty container" << std::endl;
@@ -64,6 +60,21 @@ namespace at_tests {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Finished" << std::endl;
}
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_map<std::string, int>* test_map;
static boost::unordered_node_map<std::string, int>* test_node_map;
// clang-format off
UNORDERED_TEST(at_tests, ((test_map)(test_node_map)))
// clang-format on
#else
static boost::unordered_map<std::string, int>* test_map;
// clang-format off
UNORDERED_TEST(at_tests, ((test_map)))
// clang-format on
#endif
} // namespace at_tests
RUN_TESTS()
+144 -136
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -35,6 +35,22 @@ template class instantiate_flat_map<test::minimal::assignable const,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
template <typename K, typename T, typename H, typename P, typename A>
class instantiate_node_map
{
typedef boost::unordered_node_map<K, T, H, P, A> container;
container x;
};
template class instantiate_node_map<int, int, boost::hash<int>,
std::equal_to<int>, test::minimal::allocator<int> >;
template class instantiate_node_map<test::minimal::assignable const,
test::minimal::default_assignable const,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
#else
#define INSTANTIATE(type) \
template class boost::unordered::detail::instantiate_##type
@@ -55,149 +71,101 @@ INSTANTIATE(multimap)<test::minimal::assignable, test::minimal::assignable,
test::minimal::allocator<int> >;
#endif
UNORDERED_AUTO_TEST (test0) {
template <template <class Key, class T, class H = boost::hash<Key>,
class P = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map>
static void test0_impl()
{
test::minimal::constructor_param x;
typedef std::pair<test::minimal::assignable const, test::minimal::assignable>
value_type;
value_type value(x, x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
Map<int, int> int_map;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<int, int> int_map;
boost::unordered_flat_map<int, int, boost::hash<int>, std::equal_to<int>,
Map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_map2;
boost::unordered_flat_map<test::minimal::assignable,
test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> >
map;
#else
boost::unordered_map<int, int> int_map;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_map2;
boost::unordered_map<test::minimal::assignable, test::minimal::assignable,
Map<test::minimal::assignable, test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> >
map;
#endif
container_test(int_map, std::pair<int const, int>(0, 0));
container_test(int_map2, std::pair<int const, int>(0, 0));
container_test(map, value);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_multimap2;
boost::unordered_multimap<test::minimal::assignable,
test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> >
multimap;
container_test(int_multimap, std::pair<int const, int>(0, 0));
container_test(int_multimap2, std::pair<int const, int>(0, 0));
container_test(multimap, value);
UNORDERED_AUTO_TEST (test0) {
#ifdef BOOST_UNORDERED_FOA_TESTS
test0_impl<boost::unordered_flat_map>();
test0_impl<boost::unordered_node_map>();
#else
test0_impl<boost::unordered_map>();
test0_impl<boost::unordered_multimap>();
#endif
}
UNORDERED_AUTO_TEST (equality_tests) {
template <template <class Key, class T, class H = boost::hash<Key>,
class P = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map>
static void equality_tests_impl()
{
typedef std::pair<test::minimal::copy_constructible_equality_comparable const,
test::minimal::copy_constructible_equality_comparable>
value_type;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<int, int> int_map;
Map<int, int> int_map;
boost::unordered_flat_map<int, int, boost::hash<int>, std::equal_to<int>,
Map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_map2;
boost::unordered_flat_map<
test::minimal::copy_constructible_equality_comparable,
Map<test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
map;
#else
boost::unordered_map<int, int> int_map;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_map2;
boost::unordered_map<test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
map;
#endif
equality_test(int_map);
equality_test(int_map2);
equality_test(map);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_multimap2;
boost::unordered_multimap<
test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
multimap;
equality_test(int_multimap);
equality_test(int_multimap2);
equality_test(multimap);
UNORDERED_AUTO_TEST (equality_tests) {
#ifdef BOOST_UNORDERED_FOA_TESTS
equality_tests_impl<boost::unordered_flat_map>();
equality_tests_impl<boost::unordered_node_map>();
#else
equality_tests_impl<boost::unordered_map>();
equality_tests_impl<boost::unordered_multimap>();
#endif
}
UNORDERED_AUTO_TEST (test1) {
template <template <class Key, class T, class H = boost::hash<Key>,
class P = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map>
static void test1_unique_impl()
{
boost::hash<int> hash;
std::equal_to<int> equal_to;
int value = 0;
std::pair<int const, int> map_value(0, 0);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
Map<int, int> map;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<int, int> map;
boost::unordered_flat_map<int, int, boost::hash<int>, std::equal_to<int>,
Map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
map2;
#else
boost::unordered_map<int, int> map;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
map2;
#endif
unordered_unique_test(map, map_value);
unordered_map_test(map, value, value);
@@ -208,27 +176,53 @@ UNORDERED_AUTO_TEST (test1) {
unordered_map_test(map2, value, value);
unordered_copyable_test(map2, value, map_value, hash, equal_to);
unordered_map_functions(map2, value, value);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
template <template <class Key, class T, class H = boost::hash<Key>,
class P = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map>
static void test1_equivalent_impl()
{
boost::unordered_multimap<int, int> multimap;
boost::hash<int> hash;
std::equal_to<int> equal_to;
int value = 0;
std::pair<int const, int> map_value(0, 0);
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
Map<int, int> map;
Map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
multimap2;
map2;
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, value, value);
unordered_copyable_test(multimap, value, map_value, hash, equal_to);
unordered_equivalent_test(map, map_value);
unordered_map_test(map, value, value);
unordered_copyable_test(map, value, map_value, hash, equal_to);
unordered_equivalent_test(multimap2, map_value);
unordered_map_test(multimap2, value, value);
unordered_copyable_test(multimap2, value, map_value, hash, equal_to);
unordered_equivalent_test(map2, map_value);
unordered_map_test(map2, value, value);
unordered_copyable_test(map2, value, map_value, hash, equal_to);
}
#endif
UNORDERED_AUTO_TEST (test1) {
#ifdef BOOST_UNORDERED_FOA_TESTS
test1_unique_impl<boost::unordered_flat_map>();
test1_unique_impl<boost::unordered_node_map>();
#else
test1_unique_impl<boost::unordered_map>();
test1_equivalent_impl<boost::unordered_multimap>();
#endif
}
UNORDERED_AUTO_TEST (test2) {
template <template <class Key, class T, class H = boost::hash<Key>,
class P = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map>
static void test2_unique_impl()
{
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
@@ -240,60 +234,66 @@ UNORDERED_AUTO_TEST (test2) {
map_value_type;
map_value_type map_value(assignable, assignable);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<test::minimal::assignable,
test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
map;
#else
boost::unordered_map<test::minimal::assignable, test::minimal::assignable,
Map<test::minimal::assignable, test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
map;
#endif
unordered_unique_test(map, map_value);
unordered_map_test(map, assignable, assignable);
unordered_copyable_test(map, assignable, map_value, hash, equal_to);
unordered_map_member_test(map, map_value);
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<test::minimal::assignable,
test::minimal::default_assignable,
Map<test::minimal::assignable, test::minimal::default_assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
map2;
#else
boost::unordered_map<test::minimal::assignable,
test::minimal::default_assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
map2;
#endif
test::minimal::default_assignable default_assignable;
unordered_map_functions(map2, assignable, default_assignable);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
template <template <class Key, class T, class H = boost::hash<Key>,
class P = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map>
static void test2_equivalent_impl()
{
test::minimal::constructor_param x;
boost::unordered_multimap<test::minimal::assignable,
test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
test::minimal::assignable assignable(x);
test::minimal::copy_constructible copy_constructible(x);
test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
typedef std::pair<test::minimal::assignable const, test::minimal::assignable>
map_value_type;
map_value_type map_value(assignable, assignable);
Map<test::minimal::assignable, test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
multimap;
map;
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, assignable, assignable);
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
unordered_map_member_test(multimap, map_value);
unordered_equivalent_test(map, map_value);
unordered_map_test(map, assignable, assignable);
unordered_copyable_test(map, assignable, map_value, hash, equal_to);
unordered_map_member_test(map, map_value);
}
#endif
UNORDERED_AUTO_TEST (test2) {
#ifdef BOOST_UNORDERED_FOA_TESTS
test2_unique_impl<boost::unordered_flat_map>();
test2_unique_impl<boost::unordered_node_map>();
#else
test2_unique_impl<boost::unordered_map>();
test2_equivalent_impl<boost::unordered_multimap>();
#endif
}
@@ -316,9 +316,17 @@ bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
UNORDERED_AUTO_TEST (lwg2059) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5);
x.erase(x.begin());
{
boost::unordered_flat_map<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5);
x.erase(x.begin());
}
{
boost::unordered_node_map<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5);
x.erase(x.begin());
}
#else
{
boost::unordered_map<lwg2059_key, int> x;
+187 -200
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -35,6 +35,21 @@ template class instantiate_flat_set<test::minimal::assignable const,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
template <typename T, typename H, typename P, typename A>
class instantiate_node_set
{
typedef boost::unordered_node_set<T, H, P, A> container;
container x;
};
template class instantiate_node_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::allocator<int> >;
template class instantiate_node_set<test::minimal::assignable const,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
#else
#define INSTANTIATE(type) \
@@ -56,153 +71,106 @@ INSTANTIATE(multiset)<test::minimal::assignable,
#endif
UNORDERED_AUTO_TEST (type_traits) {
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int> set_type;
#else
typedef boost::unordered_set<int> set_type;
#endif
typedef set_type::iterator iterator;
template <class X> static void type_traits_impl()
{
BOOST_STATIC_ASSERT(boost::is_same<int const&,
std::iterator_traits<iterator>::reference>::value);
typename std::iterator_traits<typename X::iterator>::reference>::value);
}
UNORDERED_AUTO_TEST (test0) {
UNORDERED_AUTO_TEST (type_traits) {
#ifdef BOOST_UNORDERED_FOA_TESTS
type_traits_impl<boost::unordered_flat_set<int> >();
type_traits_impl<boost::unordered_node_set<int> >();
#else
type_traits_impl<boost::unordered_set<int> >();
type_traits_impl<boost::unordered_multiset<int> >();
#endif
}
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void test0_impl()
{
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
Set<int> int_set;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> int_set;
boost::unordered_flat_set<int, boost::hash<int>, std::equal_to<int>,
Set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_set2;
boost::unordered_flat_set<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
Set<test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
set;
#else
boost::unordered_set<int> int_set;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_set2;
boost::unordered_set<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
set;
#endif
container_test(int_set, 0);
container_test(int_set2, 0);
container_test(set, assignable);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<int> int_multiset;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_multiset2;
boost::unordered_multiset<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
multiset;
container_test(int_multiset, 0);
container_test(int_multiset2, 0);
container_test(multiset, assignable);
UNORDERED_AUTO_TEST (test0) {
#ifdef BOOST_UNORDERED_FOA_TESTS
test0_impl<boost::unordered_flat_set>();
test0_impl<boost::unordered_node_set>();
#else
test0_impl<boost::unordered_set>();
test0_impl<boost::unordered_multiset>();
#endif
}
UNORDERED_AUTO_TEST (equality_tests) {
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void equality_tests_impl()
{
typedef test::minimal::copy_constructible_equality_comparable value_type;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> int_set;
Set<int> int_set;
boost::unordered_flat_set<int, boost::hash<int>, std::equal_to<int>,
Set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_set2;
boost::unordered_flat_set<
test::minimal::copy_constructible_equality_comparable,
Set<test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
set;
#else
boost::unordered_set<int> int_set;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_set2;
boost::unordered_set<test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
set;
#endif
equality_test(int_set);
equality_test(int_set2);
equality_test(set);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
boost::unordered_multiset<int> int_multiset;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_multiset2;
boost::unordered_multiset<
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
multiset;
equality_test(int_multiset);
equality_test(int_multiset2);
equality_test(multiset);
UNORDERED_AUTO_TEST (equality_tests) {
#ifdef BOOST_UNORDERED_FOA_TESTS
equality_tests_impl<boost::unordered_flat_set>();
equality_tests_impl<boost::unordered_node_set>();
#else
equality_tests_impl<boost::unordered_set>();
equality_tests_impl<boost::unordered_multiset>();
#endif
}
UNORDERED_AUTO_TEST (test1) {
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void test1_unique_impl()
{
boost::hash<int> hash;
std::equal_to<int> equal_to;
int value = 0;
Set<int> set;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set." << std::endl;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> set;
boost::unordered_flat_set<int, boost::hash<int>, std::equal_to<int>,
Set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
set2;
#else
boost::unordered_set<int> set;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
set2;
#endif
unordered_unique_test(set, value);
unordered_set_test(set, value);
@@ -211,27 +179,49 @@ UNORDERED_AUTO_TEST (test1) {
unordered_unique_test(set2, value);
unordered_set_test(set2, value);
unordered_copyable_test(set2, value, value, hash, equal_to);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset." << std::endl;
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void test1_equivalent_impl()
{
boost::unordered_multiset<int> multiset;
boost::hash<int> hash;
std::equal_to<int> equal_to;
int value = 0;
Set<int> set;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
Set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
multiset2;
set2;
unordered_equivalent_test(multiset, value);
unordered_set_test(multiset, value);
unordered_copyable_test(multiset, value, value, hash, equal_to);
unordered_equivalent_test(set, value);
unordered_set_test(set, value);
unordered_copyable_test(set, value, value, hash, equal_to);
unordered_equivalent_test(multiset2, value);
unordered_set_test(multiset2, value);
unordered_copyable_test(multiset2, value, value, hash, equal_to);
unordered_equivalent_test(set2, value);
unordered_set_test(set2, value);
unordered_copyable_test(set2, value, value, hash, equal_to);
}
#endif
UNORDERED_AUTO_TEST (test1) {
#ifdef BOOST_UNORDERED_FOA_TESTS
test1_unique_impl<boost::unordered_flat_set>();
test1_unique_impl<boost::unordered_node_set>();
#else
test1_unique_impl<boost::unordered_set>();
test1_equivalent_impl<boost::unordered_multiset>();
#endif
}
UNORDERED_AUTO_TEST (test2) {
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void test2_unique_impl()
{
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
@@ -239,155 +229,144 @@ UNORDERED_AUTO_TEST (test2) {
test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
Set<test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
set;
#else
boost::unordered_set<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
set;
#endif
unordered_unique_test(set, assignable);
unordered_set_test(set, assignable);
unordered_copyable_test(set, assignable, assignable, hash, equal_to);
unordered_set_member_test(set, assignable);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void test2_equivalent_impl()
{
test::minimal::constructor_param x;
boost::unordered_multiset<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::assignable assignable(x);
test::minimal::copy_constructible copy_constructible(x);
test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
Set<test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
multiset;
set;
unordered_equivalent_test(multiset, assignable);
unordered_set_test(multiset, assignable);
unordered_copyable_test(multiset, assignable, assignable, hash, equal_to);
unordered_set_member_test(multiset, assignable);
unordered_equivalent_test(set, assignable);
unordered_set_test(set, assignable);
unordered_copyable_test(set, assignable, assignable, hash, equal_to);
unordered_set_member_test(set, assignable);
}
#endif
UNORDERED_AUTO_TEST (test2) {
#ifdef BOOST_UNORDERED_FOA_TESTS
test2_unique_impl<boost::unordered_flat_set>();
test2_unique_impl<boost::unordered_node_set>();
#else
test2_unique_impl<boost::unordered_set>();
test2_equivalent_impl<boost::unordered_multiset>();
#endif
}
UNORDERED_AUTO_TEST (movable1_tests) {
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void movable1_tests_impl()
{
test::minimal::constructor_param x;
test::minimal::movable1 movable1(x);
test::minimal::hash<test::minimal::movable1> hash(x);
test::minimal::equal_to<test::minimal::movable1> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<test::minimal::movable1,
test::minimal::hash<test::minimal::movable1>,
Set<test::minimal::movable1, test::minimal::hash<test::minimal::movable1>,
test::minimal::equal_to<test::minimal::movable1>,
test::minimal::allocator<test::minimal::movable1> >
set;
#else
boost::unordered_set<test::minimal::movable1,
test::minimal::hash<test::minimal::movable1>,
test::minimal::equal_to<test::minimal::movable1>,
test::minimal::allocator<test::minimal::movable1> >
set;
#endif
// TODO: find out why Daniel had this commented out and if we need it and the
// corresponding equivalent impl
//
// unordered_unique_test(set, movable1);
unordered_set_test(set, movable1);
unordered_movable_test(set, movable1, movable1, hash, equal_to);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::movable1,
test::minimal::hash<test::minimal::movable1>,
test::minimal::equal_to<test::minimal::movable1>,
test::minimal::allocator<test::minimal::movable1> >
multiset;
// unordered_equivalent_test(multiset, movable1);
unordered_set_test(multiset, movable1);
unordered_movable_test(multiset, movable1, movable1, hash, equal_to);
UNORDERED_AUTO_TEST (movable1_tests) {
#ifdef BOOST_UNORDERED_FOA_TESTS
movable1_tests_impl<boost::unordered_flat_set>();
movable1_tests_impl<boost::unordered_node_set>();
#else
movable1_tests_impl<boost::unordered_set>();
movable1_tests_impl<boost::unordered_multiset>();
#endif
}
UNORDERED_AUTO_TEST (movable2_tests) {
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void movable2_tests_impl()
{
test::minimal::constructor_param x;
test::minimal::movable2 movable2(x);
test::minimal::hash<test::minimal::movable2> hash(x);
test::minimal::equal_to<test::minimal::movable2> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<test::minimal::movable2,
test::minimal::hash<test::minimal::movable2>,
Set<test::minimal::movable2, test::minimal::hash<test::minimal::movable2>,
test::minimal::equal_to<test::minimal::movable2>,
test::minimal::allocator<test::minimal::movable2> >
set;
#else
boost::unordered_set<test::minimal::movable2,
test::minimal::hash<test::minimal::movable2>,
test::minimal::equal_to<test::minimal::movable2>,
test::minimal::allocator<test::minimal::movable2> >
set;
#endif
// unordered_unique_test(set, movable2);
unordered_set_test(set, movable2);
unordered_movable_test(set, movable2, movable2, hash, equal_to);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
UNORDERED_AUTO_TEST (movable2_tests) {
boost::unordered_multiset<test::minimal::movable2,
test::minimal::hash<test::minimal::movable2>,
test::minimal::equal_to<test::minimal::movable2>,
test::minimal::allocator<test::minimal::movable2> >
multiset;
// unordered_equivalent_test(multiset, movable2);
unordered_set_test(multiset, movable2);
unordered_movable_test(multiset, movable2, movable2, hash, equal_to);
#ifdef BOOST_UNORDERED_FOA_TESTS
movable2_tests_impl<boost::unordered_flat_set>();
movable2_tests_impl<boost::unordered_node_set>();
#else
movable2_tests_impl<boost::unordered_set>();
movable2_tests_impl<boost::unordered_multiset>();
#endif
}
UNORDERED_AUTO_TEST (destructible_tests) {
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void destructible_tests_impl()
{
test::minimal::constructor_param x;
test::minimal::destructible destructible(x);
test::minimal::hash<test::minimal::destructible> hash(x);
test::minimal::equal_to<test::minimal::destructible> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<test::minimal::destructible,
Set<test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> >
set;
#else
boost::unordered_set<test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> >
set;
#endif
unordered_destructible_test(set);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> >
multiset;
unordered_destructible_test(multiset);
UNORDERED_AUTO_TEST (destructible_tests) {
#ifdef BOOST_UNORDERED_FOA_TESTS
destructible_tests_impl<boost::unordered_flat_set>();
destructible_tests_impl<boost::unordered_node_set>();
#else
destructible_tests_impl<boost::unordered_set>();
destructible_tests_impl<boost::unordered_multiset>();
#endif
}
@@ -410,9 +389,17 @@ bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
UNORDERED_AUTO_TEST (lwg2059) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<lwg2059_key> x;
x.emplace(lwg2059_key(10));
x.erase(x.begin());
{
boost::unordered_flat_set<lwg2059_key> x;
x.emplace(lwg2059_key(10));
x.erase(x.begin());
}
{
boost::unordered_node_set<lwg2059_key> x;
x.emplace(lwg2059_key(10));
x.erase(x.begin());
}
#else
{
boost::unordered_set<lwg2059_key> x;
+14 -5
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2010 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// Copyright (C) 2022-2023 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -655,23 +655,27 @@ namespace constructor_tests {
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_map;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_node_map;
UNORDERED_TEST(constructor_tests1,
((test_map_std_alloc)(test_set)(test_map))(
((test_map_std_alloc)(test_set)(test_node_set)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(constructor_tests2,
((test_set)(test_map))(
((test_set)(test_node_set)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(map_constructor_test,
((test_map_std_alloc)(test_map))(
((test_map_std_alloc)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(no_alloc_default_construct_test,
((test_set)(test_map))(
((test_set)(test_node_set)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
#else
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
@@ -709,6 +713,8 @@ namespace constructor_tests {
std::initializer_list<int> init;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> x1 = init;
boost::unordered_node_set<int> x2 = init;
BOOST_TEST(x2.empty());
#else
boost::unordered_set<int> x1 = init;
#endif
@@ -722,6 +728,9 @@ namespace constructor_tests {
UNORDERED_AUTO_TEST (test_initializer_list) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> x1 = {2, 10, 45, -5};
boost::unordered_node_set<int> x2 = {2, 10, 45, -5};
BOOST_TEST(x2.find(10) != x2.end());
BOOST_TEST(x2.find(46) == x2.end());
#else
boost::unordered_set<int> x1 = {2, 10, 45, -5};
#endif
+35 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 Christian Mazakas.
// Copyright 2021-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -137,6 +137,24 @@ void test_map()
typedef boost::unordered_flat_map<key, int, hasher, key_equal>
non_transparent_map3;
typedef boost::unordered_node_map<key, int, transparent_hasher,
transparent_key_equal>
transparent_node_map;
typedef boost::unordered_node_map<key, int, transparent_hasher, key_equal>
non_transparent_node_map1;
typedef boost::unordered_node_map<key, int, hasher, transparent_key_equal>
non_transparent_node_map2;
typedef boost::unordered_node_map<key, int, hasher, key_equal>
non_transparent_node_map3;
test_map_transparent_contains<transparent_node_map>();
test_map_non_transparent_contains<non_transparent_node_map1>();
test_map_non_transparent_contains<non_transparent_node_map2>();
test_map_non_transparent_contains<non_transparent_node_map3>();
#else
typedef boost::unordered_map<key, int, transparent_hasher,
transparent_key_equal>
@@ -254,6 +272,22 @@ void test_set()
non_transparent_set2;
typedef boost::unordered_flat_set<key, hasher, key_equal>
non_transparent_set3;
typedef boost::unordered_node_set<key, transparent_hasher,
transparent_key_equal>
transparent_node_set;
typedef boost::unordered_node_set<key, transparent_hasher, key_equal>
non_transparent_node_set1;
typedef boost::unordered_node_set<key, hasher, transparent_key_equal>
non_transparent_node_set2;
typedef boost::unordered_node_set<key, hasher, key_equal>
non_transparent_node_set3;
test_set_transparent_contains<transparent_node_set>();
test_set_non_transparent_contains<non_transparent_node_set1>();
test_set_non_transparent_contains<non_transparent_node_set2>();
test_set_non_transparent_contains<non_transparent_node_set3>();
#else
typedef boost::unordered_set<key, transparent_hasher, transparent_key_equal>
transparent_set;
+73 -12
View File
@@ -1,18 +1,18 @@
// Copyright 2006-2009 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// Copyright (C) 2022-2023 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
#include "../objects/cxx11_allocator.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/equivalent.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/test.hpp"
#include "../helpers/tracker.hpp"
#include "../objects/cxx11_allocator.hpp"
#include "../objects/test.hpp"
test::seed_t initialize_seed(9063);
@@ -482,31 +482,82 @@ namespace copy_tests {
allocator<std::pair<int const, int> > >*
test_map_trivially_copyable_no_construct;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_node_map;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
test_node_set_select_copy;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::select_copy> >*
test_node_map_select_copy;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
test_node_set_no_select_copy;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::no_select_copy> >*
test_node_map_no_select_copy;
boost::unordered_node_set<int, test::hash, test::equal_to,
test::allocator1<int> >* test_node_set_trivially_copyable;
boost::unordered_node_map<int, int, test::hash, test::equal_to,
test::allocator1<std::pair<int const, int> > >*
test_node_map_trivially_copyable;
boost::unordered_node_set<int, test::hash, test::equal_to,
std::allocator<int> >* test_node_set_trivially_copyable_std_allocator;
boost::unordered_node_map<int, int, test::hash, test::equal_to,
std::allocator<std::pair<int const, int> > >*
test_node_map_trivially_copyable_std_allocator;
boost::unordered_node_set<int, test::hash, test::equal_to, allocator<int> >*
test_node_set_trivially_copyable_no_construct;
boost::unordered_node_map<int, int, test::hash, test::equal_to,
allocator<std::pair<int const, int> > >*
test_node_map_trivially_copyable_no_construct;
// clang-format off
UNORDERED_TEST(copy_construct_tests1,
((test_set)(test_map)(test_set_select_copy)(test_map_select_copy)
(test_set_no_select_copy)(test_map_no_select_copy)
(test_set_trivially_copyable)(test_map_trivially_copyable))
(test_set_trivially_copyable)(test_map_trivially_copyable)
(test_node_set)(test_node_map)(test_node_set_select_copy)(test_node_map_select_copy)
(test_node_set_no_select_copy)(test_node_map_no_select_copy)
(test_node_set_trivially_copyable)(test_node_map_trivially_copyable))
((default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(copy_construct_tests2,
((test_set)(test_map)(test_set_select_copy)(test_map_select_copy)
(test_set_no_select_copy)(test_map_no_select_copy)
(test_set_trivially_copyable)(test_map_trivially_copyable))
(test_set_trivially_copyable)(test_map_trivially_copyable)
(test_node_set)(test_node_map)(test_node_set_select_copy)(test_node_map_select_copy)
(test_node_set_no_select_copy)(test_node_map_no_select_copy)
(test_node_set_trivially_copyable)(test_node_map_trivially_copyable))
((default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(copy_construct_tests_std_allocator1,
((test_set_trivially_copyable_std_allocator)
(test_map_trivially_copyable_std_allocator)
(test_set_trivially_copyable_no_construct)
(test_map_trivially_copyable_no_construct))
(test_map_trivially_copyable_no_construct)
(test_node_set_trivially_copyable_std_allocator)
(test_node_map_trivially_copyable_std_allocator)
(test_node_set_trivially_copyable_no_construct)
(test_node_map_trivially_copyable_no_construct))
((default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(copy_construct_tests_std_allocator2,
((test_set_trivially_copyable_std_allocator)
(test_map_trivially_copyable_std_allocator)
(test_set_trivially_copyable_no_construct)
(test_map_trivially_copyable_no_construct))
(test_map_trivially_copyable_no_construct)
(test_node_set_trivially_copyable_std_allocator)
(test_node_map_trivially_copyable_std_allocator)
(test_node_set_trivially_copyable_no_construct)
(test_node_map_trivially_copyable_no_construct))
((default_generator)(generate_collisions)(limited_range)))
// clang-format on
#else
@@ -545,13 +596,23 @@ namespace copy_tests {
test::equal_to, test::cxx11_allocator<test::object, test::no_select_copy> >*
test_multimap_no_select_copy;
// clang-format off
UNORDERED_TEST(copy_construct_tests1,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_select_copy)(test_multiset_select_copy)(test_map_select_copy)(test_multimap_select_copy)(test_set_no_select_copy)(test_multiset_no_select_copy)(test_map_no_select_copy)(test_multimap_no_select_copy))(
((test_set)(test_multiset)(test_map)(test_multimap)
(test_set_select_copy)(test_multiset_select_copy)
(test_map_select_copy)(test_multimap_select_copy)
(test_set_no_select_copy)(test_multiset_no_select_copy)
(test_map_no_select_copy)(test_multimap_no_select_copy))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(copy_construct_tests2,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_select_copy)(test_multiset_select_copy)(test_map_select_copy)(test_multimap_select_copy)(test_set_no_select_copy)(test_multiset_no_select_copy)(test_map_no_select_copy)(test_multimap_no_select_copy))(
((test_set)(test_multiset)(test_map)(test_multimap)
(test_set_select_copy)(test_multiset_select_copy)
(test_map_select_copy)(test_multimap_select_copy)
(test_set_no_select_copy)(test_multiset_no_select_copy)
(test_map_no_select_copy)(test_multimap_no_select_copy))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#endif
} // namespace copy_tests
+74 -44
View File
@@ -179,18 +179,13 @@ namespace emplace_tests {
};
UNORDERED_AUTO_TEST (emplace_set) {
template <class X> static void emplace_set(X*)
{
test::check_instances check_;
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<emplace_value,
boost::hash<emplace_value> >
container;
#else
typedef boost::unordered_set<emplace_value, boost::hash<emplace_value> >
container;
#endif
typedef container::iterator iterator;
typedef X container;
typedef typename container::iterator iterator;
typedef std::pair<iterator, bool> return_type;
container x(10);
iterator i1;
@@ -225,7 +220,7 @@ namespace emplace_tests {
BOOST_TEST(r1.first == x.find(v2));
BOOST_TEST_EQ(check_.instances(), 4);
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST_EQ(check_.constructions(), 6);
BOOST_TEST_EQ(check_.constructions(), 6);
#else
BOOST_TEST_EQ(check_.constructions(), 4);
#endif
@@ -294,6 +289,21 @@ namespace emplace_tests {
BOOST_TEST(x.count(v4) == 1);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_set<emplace_value, boost::hash<emplace_value> >*
test_set;
static boost::unordered_node_set<emplace_value, boost::hash<emplace_value> >*
test_node_set;
UNORDERED_TEST(emplace_set, ((test_set)(test_node_set)))
#else
static boost::unordered_set<emplace_value, boost::hash<emplace_value> >*
test_set;
UNORDERED_TEST(emplace_set, ((test_set)))
#endif
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (emplace_multiset) {
test::check_instances check_;
@@ -374,18 +384,12 @@ namespace emplace_tests {
}
#endif
UNORDERED_AUTO_TEST (emplace_map) {
template <class X> static void emplace_map(X*)
{
test::check_instances check_;
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_map<emplace_value, emplace_value,
boost::hash<emplace_value> >
container;
#else
typedef boost::unordered_map<emplace_value, emplace_value,
boost::hash<emplace_value> >
container;
#endif
typedef container::iterator iterator;
typedef X container;
typedef typename container::iterator iterator;
typedef std::pair<iterator, bool> return_type;
container x(10);
return_type r1, r2;
@@ -393,7 +397,9 @@ namespace emplace_tests {
#ifdef BOOST_UNORDERED_FOA_TESTS
// 5/8 args + duplicate
emplace_value k1(5, "", 'b', 4, 5);
BOOST_TEST_EQ(check_.constructions(), 1);
emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8);
BOOST_TEST_EQ(check_.constructions(), 2);
r1 = x.emplace(std::piecewise_construct, std::make_tuple(5, "", 'b', 4, 5),
std::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 1u);
@@ -485,18 +491,18 @@ namespace emplace_tests {
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 10);
BOOST_TEST(r1.first ==
x.emplace_hint(r1.first, boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(15, "jkjk")));
BOOST_TEST(r1.first ==
x.emplace_hint(r2.first, boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(275, "xxx", 'm', 6)));
BOOST_TEST(r1.first ==
x.emplace_hint(x.end(), boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(-10, "blah blah", '\0')));
BOOST_TEST(r1.first == x.emplace_hint(r1.first,
boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(15, "jkjk")));
BOOST_TEST(r1.first == x.emplace_hint(r2.first,
boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(275, "xxx", 'm', 6)));
BOOST_TEST(
r1.first == x.emplace_hint(x.end(), boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(-10, "blah blah", '\0')));
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(x.find(k2)->second == m2);
BOOST_TEST_EQ(check_.instances(), 8);
@@ -504,6 +510,21 @@ namespace emplace_tests {
#endif
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_map<emplace_value, emplace_value,
boost::hash<emplace_value> >* test_map;
static boost::unordered_node_map<emplace_value, emplace_value,
boost::hash<emplace_value> >* test_node_map;
UNORDERED_TEST(emplace_map, ((test_map)(test_node_map)))
#else
static boost::unordered_map<emplace_value, emplace_value,
boost::hash<emplace_value> >* test_map;
UNORDERED_TEST(emplace_map, ((test_map)))
#endif
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (emplace_multimap) {
test::check_instances check_;
@@ -571,14 +592,13 @@ namespace emplace_tests {
}
#endif
UNORDERED_AUTO_TEST (try_emplace) {
template <class X> static void try_emplace(X*)
{
test::check_instances check_;
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_map<int, emplace_value> container;
#else
typedef boost::unordered_map<int, emplace_value> container;
#endif
typedef container::iterator iterator;
typedef X container;
typedef typename container::iterator iterator;
typedef std::pair<iterator, bool> return_type;
container x(10);
return_type r1, r2, r3;
@@ -615,12 +635,22 @@ namespace emplace_tests {
BOOST_TEST_EQ(check_.constructions(), 4);
BOOST_TEST(r2.first == x.try_emplace(r2.first, k2, 808709, "what"));
BOOST_TEST(
r2.first ==
x.try_emplace(r2.first, k2, 10, "xxx", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST(r2.first == x.try_emplace(r2.first, k2, 10, "xxx", 'a', 4, 5, 6,
7, 8, 9, 10));
BOOST_TEST(r2.first->second == m2);
BOOST_TEST_EQ(x.size(), 2u);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_map<int, emplace_value>* test_int_map;
static boost::unordered_node_map<int, emplace_value>* test_int_node_map;
UNORDERED_TEST(try_emplace, ((test_int_map)(test_int_node_map)))
#else
static boost::unordered_map<int, emplace_value>* test_int_map;
UNORDERED_TEST(try_emplace, ((test_int_map)))
#endif
}
RUN_TESTS()
+131 -6
View File
@@ -1,14 +1,18 @@
// Copyright 2008-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include <boost/preprocessor/seq.hpp>
#include <list>
#include "../helpers/test.hpp"
// TODO: this test needs to be someday cleaned up to not be so heavily
// macro-generated
//
namespace equality_tests {
struct mod_compare
@@ -33,6 +37,12 @@ namespace equality_tests {
using boost_unordered_map =
boost::unordered_flat_map<int, int, mod_compare, mod_compare>;
using boost_unordered_node_set =
boost::unordered_node_set<int, mod_compare, mod_compare>;
using boost_unordered_node_map =
boost::unordered_node_map<int, int, mod_compare, mod_compare>;
#define UNORDERED_EQUALITY_MULTISET_TEST(seq1, op, seq2) \
{ \
}
@@ -64,14 +74,46 @@ namespace equality_tests {
}
#endif
#ifdef BOOST_UNORDERED_FOA_TESTS
#define UNORDERED_EQUALITY_SET_TEST(seq1, op, seq2) \
{ \
boost_unordered_set set1, set2; \
boost_unordered_set set1, set2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
BOOST_TEST(set1 op set2); \
} \
{ \
boost_unordered_node_set set1, set2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
BOOST_TEST(set1 op set2); \
}
#else
#define UNORDERED_EQUALITY_SET_TEST(seq1, op, seq2) \
{ \
boost_unordered_set set1, set2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
BOOST_TEST(set1 op set2); \
}
#endif
#ifdef BOOST_UNORDERED_FOA_TESTS
#define UNORDERED_EQUALITY_MAP_TEST(seq1, op, seq2) \
{ \
boost_unordered_map map1, map2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
BOOST_TEST(map1 op map2); \
} \
\
{ \
boost_unordered_node_map map1, map2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
BOOST_TEST(map1 op map2); \
}
#else
#define UNORDERED_EQUALITY_MAP_TEST(seq1, op, seq2) \
{ \
boost_unordered_map map1, map2; \
@@ -79,6 +121,7 @@ namespace equality_tests {
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
BOOST_TEST(map1 op map2); \
}
#endif
#define UNORDERED_SET_INSERT(r, set, item) set.insert(item);
#define UNORDERED_MAP_INSERT(r, map, item) \
@@ -86,10 +129,51 @@ namespace equality_tests {
UNORDERED_AUTO_TEST (equality_size_tests) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> x1, x2;
{
boost::unordered_flat_set<int> x1, x2;
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
x1.insert(1);
BOOST_TEST(x1 != x2);
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
x2.insert(1);
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
x2.insert(2);
BOOST_TEST(x1 != x2);
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
}
{
boost::unordered_node_set<int> x1, x2;
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
x1.insert(1);
BOOST_TEST(x1 != x2);
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
x2.insert(1);
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
x2.insert(2);
BOOST_TEST(x1 != x2);
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
}
#else
boost::unordered_set<int> x1, x2;
#endif
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
@@ -108,6 +192,7 @@ namespace equality_tests {
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
#endif
}
UNORDERED_AUTO_TEST (equality_key_value_tests) {
@@ -156,6 +241,45 @@ namespace equality_tests {
// different hash functions but the same equality predicate.
UNORDERED_AUTO_TEST (equality_different_hash_test) {
#ifdef BOOST_UNORDERED_FOA_TESTS
{
typedef boost_unordered_set set;
set set1(0, mod_compare(false), mod_compare(false));
set set2(0, mod_compare(true), mod_compare(true));
BOOST_TEST(set1 == set2);
set1.insert(1);
set2.insert(2);
BOOST_TEST(set1 != set2);
set1.insert(2);
set2.insert(1);
BOOST_TEST(set1 == set2);
set1.insert(10);
set2.insert(20);
BOOST_TEST(set1 != set2);
set1.insert(20);
set2.insert(10);
BOOST_TEST(set1 == set2);
}
{
typedef boost_unordered_node_set set;
set set1(0, mod_compare(false), mod_compare(false));
set set2(0, mod_compare(true), mod_compare(true));
BOOST_TEST(set1 == set2);
set1.insert(1);
set2.insert(2);
BOOST_TEST(set1 != set2);
set1.insert(2);
set2.insert(1);
BOOST_TEST(set1 == set2);
set1.insert(10);
set2.insert(20);
BOOST_TEST(set1 != set2);
set1.insert(20);
set2.insert(10);
BOOST_TEST(set1 == set2);
}
#else
typedef boost_unordered_set set;
set set1(0, mod_compare(false), mod_compare(false));
set set2(0, mod_compare(true), mod_compare(true));
@@ -172,7 +296,8 @@ namespace equality_tests {
set1.insert(20);
set2.insert(10);
BOOST_TEST(set1 == set2);
#endif
}
}
} // namespace equality_tests
RUN_TESTS()
+22 -3
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -36,9 +36,21 @@ UNORDERED_AUTO_TEST (set_tests) {
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int> set;
test_equal_insertion<set>(values[0], values[0] + 1);
test_equal_insertion<set>(values[1], values[1] + 2);
test_equal_insertion<set>(values[2], values[2] + 2);
test_equal_insertion<set>(values[3], values[3] + 2);
test_equal_insertion<set>(values[4], values[4] + 3);
typedef boost::unordered_node_set<int> node_set;
test_equal_insertion<node_set>(values[0], values[0] + 1);
test_equal_insertion<node_set>(values[1], values[1] + 2);
test_equal_insertion<node_set>(values[2], values[2] + 2);
test_equal_insertion<node_set>(values[3], values[3] + 2);
test_equal_insertion<node_set>(values[4], values[4] + 3);
#else
typedef boost::unordered_set<int> set;
#endif
test_equal_insertion<set>(values[0], values[0] + 1);
test_equal_insertion<set>(values[1], values[1] + 2);
@@ -52,6 +64,8 @@ UNORDERED_AUTO_TEST (set_tests) {
test_equal_insertion<multiset>(values[2], values[2] + 2);
test_equal_insertion<multiset>(values[3], values[3] + 2);
test_equal_insertion<multiset>(values[4], values[4] + 3);
#endif
}
UNORDERED_AUTO_TEST (map_tests) {
@@ -65,11 +79,16 @@ UNORDERED_AUTO_TEST (map_tests) {
v[2].push_back(std::pair<int const, int>(9, 13));
v[2].push_back(std::pair<int const, int>(432, 24));
for (int i = 0; i < 5; ++i)
#ifdef BOOST_UNORDERED_FOA_TESTS
for (int i = 0; i < 5; ++i)
test_equal_insertion<boost::unordered_flat_map<int, int> >(
v[i].begin(), v[i].end());
for (int i2 = 0; i2 < 5; ++i2)
test_equal_insertion<boost::unordered_node_map<int, int> >(
v[i2].begin(), v[i2].end());
#else
for (int i = 0; i < 5; ++i)
test_equal_insertion<boost::unordered_map<int, int> >(
v[i].begin(), v[i].end());
+2
View File
@@ -110,6 +110,8 @@ UNORDERED_AUTO_TEST (unordered_erase_if) {
#ifdef BOOST_UNORDERED_FOA_TESTS
test_map_erase_if<boost::unordered_flat_map<std::string, int> >();
test_set_erase_if<boost::unordered_flat_set<int> >();
test_map_erase_if<boost::unordered_node_map<std::string, int> >();
test_set_erase_if<boost::unordered_node_set<int> >();
#else
test_map_erase_if<boost::unordered_map<std::string, int> >();
test_map_erase_if<boost::unordered_multimap<std::string, int> >();
+9 -2
View File
@@ -270,10 +270,16 @@ namespace erase_tests {
test::allocator1<test::object> >* test_set;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_map;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_node_map;
// clang-format off
UNORDERED_TEST(
erase_tests1, ((test_set)(test_map))(
erase_tests1, ((test_set)(test_map)(test_node_set)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#else
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
@@ -284,10 +290,11 @@ namespace erase_tests {
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap;
// clang-format off
UNORDERED_TEST(
erase_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#endif
}
+17 -10
View File
@@ -1,14 +1,10 @@
// Copyright 2016 Daniel James.
// Copyright 2023 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/equivalent.hpp"
#include "../helpers/helpers.hpp"
@@ -113,6 +109,19 @@ namespace extract_tests {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
}
using test::default_generator;
using test::generate_collisions;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_node_map;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set;
UNORDERED_TEST(extract_tests1,
((test_node_map)(test_node_set))((default_generator)(generate_collisions)))
#else
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
@@ -122,12 +131,10 @@ namespace extract_tests {
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(
extract_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)))
}
#endif
} // namespace extract_tests
RUN_TESTS()
+6 -2
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// Copyright (C) 2022-2023 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -138,9 +138,13 @@ namespace find_tests {
test::allocator2<test::object> >* test_set;
boost::unordered_flat_map<test::object, test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_node_set;
boost::unordered_node_map<test::object, test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_node_map;
UNORDERED_TEST(
find_tests1, ((test_set)(test_map))(
find_tests1, ((test_set)(test_map)(test_node_set)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
#else
boost::unordered_set<test::object, test::hash, test::equal_to,
+43 -1
View File
@@ -1,6 +1,6 @@
// Copyright 2008-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -8,6 +8,7 @@
#include "../helpers/prefix.hpp"
#ifdef BOOST_UNORDERED_FOA_TESTS
#include <boost/unordered/unordered_flat_map_fwd.hpp>
#include <boost/unordered/unordered_node_map_fwd.hpp>
#include <boost/unordered/detail/implementation.hpp>
#else
#include <boost/unordered/unordered_map_fwd.hpp>
@@ -23,6 +24,13 @@ void call_swap(
swap(x, y);
}
template <typename T>
void call_swap(
boost::unordered_node_map<T, T>& x, boost::unordered_node_map<T, T>& y)
{
swap(x, y);
}
template <typename T>
bool call_equals(
boost::unordered_flat_map<T, T>& x, boost::unordered_flat_map<T, T>& y)
@@ -30,6 +38,13 @@ bool call_equals(
return x == y;
}
template <typename T>
bool call_equals(
boost::unordered_node_map<T, T>& x, boost::unordered_node_map<T, T>& y)
{
return x == y;
}
template <typename T>
bool call_not_equals(
boost::unordered_flat_map<T, T>& x, boost::unordered_flat_map<T, T>& y)
@@ -37,7 +52,15 @@ bool call_not_equals(
return x != y;
}
template <typename T>
bool call_not_equals(
boost::unordered_node_map<T, T>& x, boost::unordered_node_map<T, T>& y)
{
return x != y;
}
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/unordered/unordered_node_map.hpp>
#else
template <typename T>
void call_swap(boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y)
@@ -85,6 +108,7 @@ bool call_not_equals(
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_map<int, int> int_map;
typedef boost::unordered_node_map<int, int> int_node_map;
#else
typedef boost::unordered_map<int, int> int_map;
typedef boost::unordered_multimap<int, int> int_multimap;
@@ -106,6 +130,24 @@ UNORDERED_AUTO_TEST (use_map_fwd_declared_function) {
BOOST_TEST(call_not_equals(x, y));
}
#ifdef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (use_node_map_fwd_declared_function) {
int_node_map x, y;
x[1] = 2;
y[2] = 1;
call_swap(x, y);
BOOST_TEST(y.find(1) != y.end() && y.find(1)->second == 2);
BOOST_TEST(y.find(2) == y.end());
BOOST_TEST(x.find(1) == x.end());
BOOST_TEST(x.find(2) != x.end() && x.find(2)->second == 1);
BOOST_TEST(!call_equals(x, y));
BOOST_TEST(call_not_equals(x, y));
}
#endif
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (use_multimap_fwd_declared_function) {
int_multimap x, y;
+58 -2
View File
@@ -1,6 +1,6 @@
// Copyright 2008-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -8,6 +8,7 @@
#include "../helpers/prefix.hpp"
#ifdef BOOST_UNORDERED_FOA_TESTS
#include <boost/unordered/unordered_flat_set_fwd.hpp>
#include <boost/unordered/unordered_node_set_fwd.hpp>
#include <boost/unordered/detail/implementation.hpp>
#else
#include <boost/unordered/unordered_set_fwd.hpp>
@@ -31,12 +32,22 @@ template <class Value, class Hash, class Pred, class Alloc>
true_type is_unordered_set_impl(
boost::unordered_flat_set<Value, Hash, Pred, Alloc>*);
template <class Value, class Hash, class Pred, class Alloc>
true_type is_unordered_set_impl(
boost::unordered_node_set<Value, Hash, Pred, Alloc>*);
template <typename T>
void call_swap(boost::unordered_flat_set<T>& x, boost::unordered_flat_set<T>& y)
{
swap(x, y);
}
template <typename T>
void call_swap(boost::unordered_node_set<T>& x, boost::unordered_node_set<T>& y)
{
swap(x, y);
}
template <typename T>
bool call_equals(
boost::unordered_flat_set<T>& x, boost::unordered_flat_set<T>& y)
@@ -44,12 +55,26 @@ bool call_equals(
return x == y;
}
template <typename T>
bool call_equals(
boost::unordered_node_set<T>& x, boost::unordered_node_set<T>& y)
{
return x == y;
}
template <typename T>
bool call_not_equals(
boost::unordered_flat_set<T>& x, boost::unordered_flat_set<T>& y)
{
return x != y;
}
template <typename T>
bool call_not_equals(
boost::unordered_node_set<T>& x, boost::unordered_node_set<T>& y)
{
return x != y;
}
#else
template <class Value, class Hash, class Pred, class Alloc>
true_type is_unordered_set_impl(
@@ -100,6 +125,7 @@ bool call_not_equals(
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int> int_set;
typedef boost::unordered_node_set<int> int_node_set;
#else
typedef boost::unordered_set<int> int_set;
typedef boost::unordered_multiset<int> int_multiset;
@@ -107,10 +133,15 @@ typedef boost::unordered_multiset<int> int_multiset;
UNORDERED_AUTO_TEST (use_fwd_declared_trait_without_definition) {
BOOST_TEST(sizeof(is_unordered_set_impl((int_set*)0)) == sizeof(true_type));
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST(
sizeof(is_unordered_set_impl((int_node_set*)0)) == sizeof(true_type));
#endif
}
#ifdef BOOST_UNORDERED_FOA_TESTS
#include <boost/unordered/unordered_flat_set.hpp>
#include <boost/unordered/unordered_node_set.hpp>
#else
#include <boost/unordered_set.hpp>
#endif
@@ -118,10 +149,17 @@ UNORDERED_AUTO_TEST (use_fwd_declared_trait_without_definition) {
UNORDERED_AUTO_TEST (use_fwd_declared_trait) {
int_set x;
BOOST_TEST(sizeof(is_unordered_set_impl(&x)) == sizeof(true_type));
BOOST_TEST(sizeof(is_unordered_set_impl((int*)0)) == sizeof(false_type));
}
#ifdef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (use_node_fwd_declared_trait) {
int_node_set x;
BOOST_TEST(sizeof(is_unordered_set_impl(&x)) == sizeof(true_type));
BOOST_TEST(sizeof(is_unordered_set_impl((int*)0)) == sizeof(false_type));
}
#endif
UNORDERED_AUTO_TEST (use_set_fwd_declared_function) {
int_set x, y;
x.insert(1);
@@ -138,6 +176,24 @@ UNORDERED_AUTO_TEST (use_set_fwd_declared_function) {
BOOST_TEST(call_not_equals(x, y));
}
#ifdef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (use_node_set_fwd_declared_function) {
int_node_set x, y;
x.insert(1);
y.insert(2);
call_swap(x, y);
BOOST_TEST(y.find(1) != y.end());
BOOST_TEST(y.find(2) == y.end());
BOOST_TEST(x.find(1) == x.end());
BOOST_TEST(x.find(2) != x.end());
BOOST_TEST(!call_equals(x, y));
BOOST_TEST(call_not_equals(x, y));
}
#endif
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (use_multiset_fwd_declared_function) {
int_multiset x, y;
+9 -8
View File
@@ -1,6 +1,6 @@
// Copyright 2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -13,11 +13,12 @@ namespace x {
{
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<D, D> x;
boost::unordered_node_map<D, D> y;
#else
boost::unordered_map<D, D> x;
#endif
};
}
} // namespace x
namespace incomplete_test {
// Declare, but don't define some types.
@@ -33,11 +34,11 @@ namespace incomplete_test {
typedef boost::unordered_flat_map<value, value, hash, equals,
allocator<std::pair<value const, value> > >
map;
typedef boost::unordered_flat_map<value, value, hash, equals,
typedef boost::unordered_flat_set<value, hash, equals, allocator<value> > set;
typedef boost::unordered_node_map<value, value, hash, equals,
allocator<std::pair<value const, value> > >
multimap;
typedef boost::unordered_flat_set<value, hash, equals, allocator<value> > set;
typedef boost::unordered_flat_set<value, hash, equals, allocator<value> >
typedef boost::unordered_node_set<value, hash, equals, allocator<value> >
multiset;
#else
typedef boost::unordered_map<value, value, hash, equals,
@@ -97,7 +98,7 @@ namespace incomplete_test {
};
struct struct2
{
boost::unordered_flat_map<struct2, struct2, hash, equals,
boost::unordered_node_map<struct2, struct2, hash, equals,
allocator<std::pair<struct2 const, struct2> > >
x;
};
@@ -107,7 +108,7 @@ namespace incomplete_test {
};
struct struct4
{
boost::unordered_flat_set<struct4, hash, equals, allocator<struct4> > x;
boost::unordered_node_set<struct4, hash, equals, allocator<struct4> > x;
};
#else
struct struct1
@@ -195,7 +196,7 @@ namespace incomplete_test {
bool operator==(struct2 const&, struct2 const&) { return true; }
bool operator==(struct3 const&, struct3 const&) { return true; }
bool operator==(struct4 const&, struct4 const&) { return true; }
}
} // namespace incomplete_test
int main()
{
+209 -16
View File
@@ -7,9 +7,16 @@
#error "This test is only for the FOA-style conatiners"
#endif
#include "../helpers/test.hpp"
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include <boost/config.hpp>
#if defined(BOOST_LIBSTDCXX_VERSION)
#if BOOST_LIBSTDCXX_VERSION < 60000
#define BOOST_UNORDERED_NO_INIT_TYPE_TESTS
#endif
#endif
struct move_only
{
@@ -26,18 +33,49 @@ struct move_only
}
};
namespace std{
namespace std {
template <> struct hash<move_only>
{
std::size_t operator()(move_only const& mo) const noexcept
template <> struct hash<move_only>
{
return std::hash<int>()(mo.x_);
std::size_t operator()(move_only const& mo) const noexcept
{
return std::hash<int>()(mo.x_);
}
};
} // namespace std
#ifndef BOOST_UNORDERED_NO_INIT_TYPE_TESTS
struct immovable
{
int x_ = -1;
immovable() = default;
immovable(int x) : x_{x} {}
immovable(immovable const&) = delete;
immovable(immovable&&) = delete;
friend bool operator==(immovable const& lhs, immovable const& rhs)
{
return lhs.x_ == rhs.x_;
}
};
namespace std {
template <> struct hash<immovable>
{
std::size_t operator()(immovable const& im) const noexcept
{
return std::hash<int>()(im.x_);
}
};
} // namespace std
#endif
struct raii_tracker
{
static unsigned move_constructs;
@@ -68,15 +106,15 @@ struct raii_tracker
}
};
namespace std{
namespace std {
template <> struct hash<raii_tracker>
{
std::size_t operator()(raii_tracker const& rt) const noexcept
template <> struct hash<raii_tracker>
{
return std::hash<int>()(rt.x_);
}
};
std::size_t operator()(raii_tracker const& rt) const noexcept
{
return std::hash<int>()(rt.x_);
}
};
} // namespace std
@@ -90,9 +128,7 @@ static void test_move_only()
boost::unordered_flat_map<move_only, int, std::hash<move_only> > map;
using init_type = decltype(map)::init_type;
static_assert(
std::is_same<decltype(std::make_pair(move_only(1), v)), init_type>::value,
"");
static_assert(std::is_same<std::pair<move_only, int>, init_type>::value, "");
map.insert(std::make_pair(move_only(1), v));
map.insert({move_only(2), v});
@@ -235,10 +271,167 @@ static void test_insert_hint_tracking()
BOOST_TEST_EQ(raii_tracker::move_constructs, 7u + 2u * map.size());
}
static void test_immovable()
{
#ifndef BOOST_UNORDERED_NO_INIT_TYPE_TESTS
int const v = 128;
boost::unordered_node_map<immovable, int, std::hash<immovable> > map;
using init_type = decltype(map)::init_type;
static_assert(std::is_same<std::pair<immovable, int>, init_type>::value, "");
map.emplace(1, v);
map.emplace(2, v);
BOOST_TEST_EQ(map.size(), 2u);
map.rehash(1024);
BOOST_TEST_GE(map.bucket_count(), 1024u);
#endif
}
static void test_insert_node_tracking()
{
raii_tracker::reset_counts();
BOOST_TEST_EQ(raii_tracker::copy_constructs, 0u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 0u);
boost::unordered_node_map<raii_tracker, raii_tracker,
std::hash<raii_tracker> >
map;
{
std::pair<raii_tracker, raii_tracker> value{1, 2};
map.insert(value);
BOOST_TEST_EQ(raii_tracker::copy_constructs, 2u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 0u);
}
{
std::pair<raii_tracker, raii_tracker> value{2, 3};
map.insert(std::move(value));
BOOST_TEST_EQ(raii_tracker::copy_constructs, 2u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 2u);
}
{
std::pair<raii_tracker const, raii_tracker> value{3, 4};
map.insert(value);
BOOST_TEST_EQ(raii_tracker::copy_constructs, 4u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 2u);
}
{
std::pair<raii_tracker const, raii_tracker> value{4, 5};
map.insert(std::move(value));
BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 3u);
}
{
map.insert(std::make_pair(5, 6));
BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 5u);
}
{
map.insert({6, 7});
BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 7u);
}
BOOST_TEST_EQ(map.size(), 6u);
map.rehash(1024);
BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 7u);
}
static void test_insert_hint_node_tracking()
{
raii_tracker::reset_counts();
BOOST_TEST_EQ(raii_tracker::copy_constructs, 0u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 0u);
boost::unordered_node_map<raii_tracker, raii_tracker,
std::hash<raii_tracker> >
map;
{
std::pair<raii_tracker, raii_tracker> value{1, 2};
map.insert(map.begin(), value);
BOOST_TEST_EQ(raii_tracker::copy_constructs, 2u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 0u);
}
{
std::pair<raii_tracker, raii_tracker> value{2, 3};
map.insert(std::move(value));
BOOST_TEST_EQ(raii_tracker::copy_constructs, 2u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 2u);
}
{
std::pair<raii_tracker const, raii_tracker> value{3, 4};
map.insert(map.begin(), value);
BOOST_TEST_EQ(raii_tracker::copy_constructs, 4u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 2u);
}
{
std::pair<raii_tracker const, raii_tracker> value{4, 5};
map.insert(map.begin(), std::move(value));
BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 3u);
}
{
map.insert(map.begin(), std::make_pair(5, 6));
BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 5u);
}
{
map.insert(map.begin(), {6, 7});
BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 7u);
}
BOOST_TEST_EQ(map.size(), 6u);
map.rehash(1024);
BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 7u);
}
int main()
{
test_move_only();
test_insert_tracking();
test_insert_hint_tracking();
test_immovable();
test_insert_node_tracking();
test_insert_hint_node_tracking();
return boost::report_errors();
}
+23 -14
View File
@@ -1,6 +1,6 @@
// Copyright 2016 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -88,12 +88,11 @@ namespace insert_hint {
}
}
#endif
UNORDERED_AUTO_TEST (insert_hint_unique) {
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int> container;
#else
typedef boost::unordered_set<int> container;
#endif
template <class X> static void insert_hint_unique(X*)
{
typedef X container;
container x;
x.insert(x.cbegin(), 10);
BOOST_TEST_EQ(x.size(), 1u);
@@ -101,12 +100,10 @@ namespace insert_hint {
test::check_equivalent_keys(x);
}
UNORDERED_AUTO_TEST (insert_hint_unique_single) {
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int> container;
#else
typedef boost::unordered_set<int> container;
#endif
template <class X> static void insert_hint_unique_single(X*)
{
typedef X container;
container x;
x.insert(10);
@@ -121,6 +118,18 @@ namespace insert_hint {
BOOST_TEST_EQ(x.count(20), 1u);
test::check_equivalent_keys(x);
}
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_set<int>* test_set;
static boost::unordered_node_set<int>* test_node_set;
UNORDERED_TEST(insert_hint_unique, ((test_set)(test_node_set)))
UNORDERED_TEST(insert_hint_unique_single, ((test_set)(test_node_set)))
#else
static boost::unordered_set<int>* test_set;
UNORDERED_TEST(insert_hint_unique, ((test_set)))
UNORDERED_TEST(insert_hint_unique_single, ((test_set)))
#endif
} // namespace insert_hint
RUN_TESTS()
+314 -151
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2010 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// Copyright (C) 2022-2023 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -17,6 +17,7 @@
#include "../helpers/input_iterator.hpp"
#include "../helpers/helpers.hpp"
#include <boost/move/core.hpp>
#include <vector>
namespace insert_tests {
@@ -219,7 +220,7 @@ namespace insert_tests {
test::check_instances check_;
X x;
const_iterator pos = x.begin();
iterator pos = x.begin();
tracker_type tracker = test::create_ordered(x);
test::random_values<X> v(1000, generator);
@@ -247,7 +248,7 @@ namespace insert_tests {
test::check_instances check_;
X x;
const_iterator pos = x.begin();
iterator pos = x.begin();
tracker_type tracker = test::create_ordered(x);
test::random_values<X> v(1000, generator);
@@ -693,6 +694,69 @@ namespace insert_tests {
BOOST_TEST_EQ(x.size(), 1000u);
}
struct pointer_constructible
{
int x;
pointer_constructible(int x_) : x(x_) {}
pointer_constructible(pointer_constructible const& p) : x(p.x) {}
pointer_constructible(pointer_constructible* const&) : x(-1) {}
pointer_constructible(BOOST_RV_REF(pointer_constructible*)) : x(-1) {}
};
struct pointer_constructible_hash
{
typedef void is_transparent;
std::size_t operator()(pointer_constructible const& p) const
{
return boost::hash<int>()(p.x);
}
};
struct pointer_constructible_equal_to
{
typedef void is_transparent;
bool operator()(
pointer_constructible const& lhs, pointer_constructible const& rhs) const
{
return lhs.x == rhs.x;
}
};
template <class X>
static void set_tests2(X*)
{
X set, set2;
pointer_constructible pc(1337);
pointer_constructible* const addr_pc = &pc;
set.insert(pc); // 1337
set.insert(&pc); // -1
set.insert(addr_pc); // -1
BOOST_TEST_EQ(set.size(), 2u);
BOOST_TEST(set.find(pc) != set.end());
BOOST_TEST(set.find(-1) != set.end());
BOOST_TEST(set.find(-2) == set.end());
set2 = set;
BOOST_TEST_EQ(set2.size(), 2u);
BOOST_TEST(set2.find(pc) != set2.end());
BOOST_TEST(set2.find(-1) != set2.end());
BOOST_TEST(set2.find(-2) == set2.end());
set.rehash(set.bucket_count() + 1);
BOOST_TEST_EQ(set.size(), 2u);
BOOST_TEST(set.find(pc) != set.end());
BOOST_TEST(set.find(-1) != set.end());
BOOST_TEST(set.find(-2) == set.end());
}
template <class X>
void try_emplace_tests(X*, test::random_generator generator)
{
@@ -892,45 +956,62 @@ namespace insert_tests {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_set_std_alloc;
boost::unordered_node_set<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_node_set_std_alloc;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_node_set<test::movable, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set;
boost::unordered_flat_map<test::movable, test::movable, test::hash,
test::equal_to, test::allocator2<test::movable> >* test_map;
boost::unordered_node_map<test::movable, test::movable, test::hash,
test::equal_to, test::allocator2<test::movable> >* test_node_map;
boost::unordered_flat_set<pointer_constructible, pointer_constructible_hash,
pointer_constructible_equal_to, test::allocator1<pointer_constructible> >*
test_pc_set;
boost::unordered_node_set<pointer_constructible, pointer_constructible_hash,
pointer_constructible_equal_to, test::allocator1<pointer_constructible> >*
test_pc_node_set;
UNORDERED_TEST(unique_insert_tests1,
((test_set_std_alloc)(test_set)(test_map))(
((test_set_std_alloc)(test_node_set_std_alloc)
(test_set)(test_node_set)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
insert_tests2, ((test_set)(test_map))(
insert_tests2, ((test_set)(test_node_set)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(unique_emplace_tests1,
((test_set_std_alloc)(test_set)(test_map))(
((test_set_std_alloc)(test_set)(test_node_set)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_emplace_tests,
((test_set_std_alloc)(test_set)(test_map))(
((test_set_std_alloc)(test_set)(test_node_set)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(default_emplace_tests,
((test_set_std_alloc)(test_set)(test_map))(
((test_set_std_alloc)(test_set)(test_node_set)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(map_tests,
((test_map))((default_generator)(generate_collisions)(limited_range)))
((test_map)(test_node_map))
((default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
map_tests2, ((test_map))((default_generator)(generate_collisions)))
map_tests2, ((test_map)(test_node_map))((default_generator)(generate_collisions)))
UNORDERED_TEST(map_insert_range_test1,
((test_map))((default_generator)(generate_collisions)(limited_range)))
((test_map)(test_node_map))((default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(map_insert_range_test2,
((test_map))((default_generator)(generate_collisions)(limited_range)))
((test_map)(test_node_map))((default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
set_tests, ((test_set_std_alloc)(test_set))((default_generator)))
set_tests, ((test_set_std_alloc)(test_set)(test_node_set))((default_generator)))
UNORDERED_TEST(set_tests2, ((test_pc_set)(test_pc_node_set)))
#else
boost::unordered_set<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_set_std_alloc;
@@ -946,6 +1027,10 @@ namespace insert_tests {
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_multimap;
boost::unordered_set<pointer_constructible, pointer_constructible_hash,
pointer_constructible_equal_to, test::allocator1<pointer_constructible> >*
test_pc_set;
UNORDERED_TEST(unique_insert_tests1,
((test_set_std_alloc)(test_set)(test_map))(
(default_generator)(generate_collisions)(limited_range)))
@@ -990,6 +1075,8 @@ namespace insert_tests {
UNORDERED_TEST(
set_tests, ((test_set_std_alloc)(test_set)(test_multiset))((default_generator)))
UNORDERED_TEST(set_tests2, ((test_pc_set)))
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -1009,23 +1096,19 @@ namespace insert_tests {
}
};
UNORDERED_AUTO_TEST (insert_initializer_list_set) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> set;
#else
boost::unordered_set<int> set;
#endif
template <template <class Key, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>, class Allocator = std::allocator<Key> >
class Set>
static void insert_initializer_list_set_impl()
{
Set<int> set;
set.insert({1, 2, 3, 1});
BOOST_TEST_EQ(set.size(), 3u);
BOOST_TEST(set.find(1) != set.end());
BOOST_TEST(set.find(4) == set.end());
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<initialize_from_two_ints> set2;
#else
boost::unordered_set<initialize_from_two_ints> set2;
#endif
Set<initialize_from_two_ints> set2;
#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))
set2.insert({{1, 2}});
#else
@@ -1053,6 +1136,16 @@ namespace insert_tests {
BOOST_TEST(set2.find({8, 7}) == set2.end());
}
UNORDERED_AUTO_TEST (insert_initializer_list_set) {
#ifdef BOOST_UNORDERED_FOA_TESTS
insert_initializer_list_set_impl<boost::unordered_flat_set>();
insert_initializer_list_set_impl<boost::unordered_node_set>();
#else
insert_initializer_list_set_impl<boost::unordered_set>();
boost::unordered_set<int> set;
#endif
}
#ifndef BOOST_UNORDERED_FOA_TESTS
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1800)
@@ -1074,18 +1167,31 @@ namespace insert_tests {
#endif
#endif
UNORDERED_AUTO_TEST (insert_initializer_list_map) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<std::string, std::string> map;
#else
boost::unordered_map<std::string, std::string> map;
#endif
// map.insert({});
template <class X> static void insert_initializer_list_map(X*)
{
X map;
BOOST_TEST(map.empty());
map.insert({{"a", "b"}, {"a", "b"}, {"d", ""}});
BOOST_TEST_EQ(map.size(), 2u);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_map<std::string, std::string>* test_str_map;
static boost::unordered_node_map<std::string, std::string>* test_str_node_map;
// clang-format off
UNORDERED_TEST(insert_initializer_list_map,
((test_str_map)(test_str_node_map)))
// clang-format on
#else
static boost::unordered_map<std::string, std::string>* test_str_map;
// clang-format off
UNORDERED_TEST(insert_initializer_list_map, ((test_str_map)))
// clang-format on
#endif
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (insert_initializer_list_multimap) {
boost::unordered_multimap<std::string, std::string> multimap;
@@ -1124,65 +1230,72 @@ namespace insert_tests {
}
};
UNORDERED_AUTO_TEST (map_emplace_test) {
{
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<int, overloaded_constructor, test::hash,
test::equal_to,
test::allocator1<std::pair<int const, overloaded_constructor> > >
x;
#else
boost::unordered_map<int, overloaded_constructor, test::hash,
test::equal_to,
test::allocator1<std::pair<int const, overloaded_constructor> > >
x;
#endif
template <class X> static void map_emplace_test(X*)
{
X x;
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
x.emplace();
BOOST_TEST(
x.find(0) != x.end() && x.find(0)->second == overloaded_constructor());
x.emplace();
BOOST_TEST(
x.find(0) != x.end() && x.find(0)->second == overloaded_constructor());
#endif
x.emplace(2, 3);
BOOST_TEST(
x.find(2) != x.end() && x.find(2)->second == overloaded_constructor(3));
x.emplace(2, 3);
BOOST_TEST(
x.find(2) != x.end() && x.find(2)->second == overloaded_constructor(3));
x.try_emplace(5);
BOOST_TEST(
x.find(5) != x.end() && x.find(5)->second == overloaded_constructor());
}
#ifndef BOOST_UNORDERED_FOA_TESTS
{
boost::unordered_multimap<int, overloaded_constructor, test::hash,
test::equal_to,
test::allocator1<std::pair<int const, overloaded_constructor> > >
x;
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
x.emplace();
BOOST_TEST(
x.find(0) != x.end() && x.find(0)->second == overloaded_constructor());
#endif
x.emplace(2, 3);
BOOST_TEST(
x.find(2) != x.end() && x.find(2)->second == overloaded_constructor(3));
}
#endif
x.try_emplace(5);
BOOST_TEST(
x.find(5) != x.end() && x.find(5)->second == overloaded_constructor());
}
UNORDERED_AUTO_TEST (set_emplace_test) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<overloaded_constructor> x;
overloaded_constructor check;
#else
boost::unordered_set<overloaded_constructor> x;
overloaded_constructor check;
#ifndef BOOST_UNORDERED_FOA_TESTS
template <class X> static void multimap_emplace_test(X*)
{
X x;
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
x.emplace();
BOOST_TEST(
x.find(0) != x.end() && x.find(0)->second == overloaded_constructor());
#endif
x.emplace(2, 3);
BOOST_TEST(
x.find(2) != x.end() && x.find(2)->second == overloaded_constructor(3));
}
#endif
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_map<int, overloaded_constructor, test::hash,
test::equal_to,
test::allocator1<std::pair<int const, overloaded_constructor> > >*
test_oc_map;
static boost::unordered_node_map<int, overloaded_constructor, test::hash,
test::equal_to,
test::allocator1<std::pair<int const, overloaded_constructor> > >*
test_oc_node_map;
UNORDERED_TEST(map_emplace_test, ((test_oc_map)(test_oc_node_map)))
#else
static boost::unordered_map<int, overloaded_constructor, test::hash,
test::equal_to,
test::allocator1<std::pair<int const, overloaded_constructor> > >*
test_oc_map;
static boost::unordered_multimap<int, overloaded_constructor, test::hash,
test::equal_to,
test::allocator1<std::pair<int const, overloaded_constructor> > >*
test_oc_multimap;
UNORDERED_TEST(map_emplace_test, ((test_oc_map)))
UNORDERED_TEST(multimap_emplace_test, ((test_oc_multimap)))
#endif
template <class X> static void set_emplace_test(X*)
{
X x;
overloaded_constructor check;
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
x.emplace();
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
@@ -1209,6 +1322,18 @@ namespace insert_tests {
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_set<overloaded_constructor>* test_oc_set;
static boost::unordered_node_set<overloaded_constructor>* test_oc_node_set;
UNORDERED_TEST(set_emplace_test, ((test_oc_set)(test_oc_node_set)))
#else
static boost::unordered_set<overloaded_constructor>* test_oc_set;
static boost::unordered_multiset<overloaded_constructor>* test_oc_multiset;
UNORDERED_TEST(set_emplace_test, ((test_oc_set)(test_oc_multiset)))
#endif
struct derived_from_piecewise_construct_t
: boost::unordered::piecewise_construct_t
{
@@ -1358,6 +1483,14 @@ namespace insert_tests {
#ifndef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_map<overloaded_constructor, overloaded_constructor,
boost::hash<overloaded_constructor>, std::equal_to<overloaded_constructor>,
test::allocator1<std::pair<overloaded_constructor const,
overloaded_constructor> > >* test_pw_oc_map;
static boost::unordered_set<std::pair<overloaded_constructor,
overloaded_constructor> >* test_pair_oc_set;
#define PIECEWISE_TEST_NAME boost_tuple_piecewise_tests
#define PIECEWISE_NAMESPACE boost::unordered
#define TUPLE_NAMESPACE boost
@@ -1389,6 +1522,14 @@ namespace insert_tests {
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_set<std::pair<overloaded_constructor,
overloaded_constructor> >* test_pair_oc_set;
static boost::unordered_node_set<std::pair<overloaded_constructor,
overloaded_constructor> >* test_pair_oc_node_set;
#endif
#define PIECEWISE_TEST_NAME std_piecewise_tests
#define PIECEWISE_NAMESPACE std
#define TUPLE_NAMESPACE std
@@ -1402,27 +1543,17 @@ RUN_TESTS_QUIET()
#else // PIECEWISE_TEST_NAME
UNORDERED_AUTO_TEST (PIECEWISE_TEST_NAME) {
#define MAP_PIECEWISE_TEST BOOST_PP_CAT(map_, PIECEWISE_TEST_NAME)
#define SET_PIECEWISE_TEST BOOST_PP_CAT(set_, PIECEWISE_TEST_NAME)
template <class X>
static void MAP_PIECEWISE_TEST(X*)
{
#if EMULATING_PIECEWISE_CONSTRUCTION
test::detail::disable_construction_tracking _scoped;
#endif
{
#if defined(BOOST_UNORDERED_FOA_TESTS)
boost::unordered_flat_map<overloaded_constructor, overloaded_constructor,
boost::hash<overloaded_constructor>,
std::equal_to<overloaded_constructor>,
test::allocator1<
std::pair<overloaded_constructor const, overloaded_constructor> > >
x;
#else
boost::unordered_map<overloaded_constructor, overloaded_constructor,
boost::hash<overloaded_constructor>,
std::equal_to<overloaded_constructor>,
test::allocator1<
std::pair<overloaded_constructor const, overloaded_constructor> > >
x;
#endif
X x;
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
@@ -1466,70 +1597,102 @@ UNORDERED_AUTO_TEST (PIECEWISE_TEST_NAME) {
x.find(overloaded_constructor(2, 3))->second ==
overloaded_constructor(4, 5, 6));
}
#ifndef BOOST_UNORDERED_FOA_TESTS
template <class X>
static void SET_PIECEWISE_TEST(X*)
{
boost::unordered_multimap<overloaded_constructor, overloaded_constructor,
boost::hash<overloaded_constructor>,
std::equal_to<overloaded_constructor>,
test::allocator1<
std::pair<overloaded_constructor const, overloaded_constructor> > >
x;
#if EMULATING_PIECEWISE_CONSTRUCTION
test::detail::disable_construction_tracking _scoped;
#endif
X x;
std::pair<overloaded_constructor, overloaded_constructor> check;
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
BOOST_TEST(
x.find(overloaded_constructor()) != x.end() &&
x.find(overloaded_constructor())->second == overloaded_constructor());
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
x.emplace(convertible_to_piecewise(), TUPLE_NAMESPACE::make_tuple(1),
TUPLE_NAMESPACE::make_tuple());
BOOST_TEST(
x.find(overloaded_constructor(1)) != x.end() &&
x.find(overloaded_constructor(1))->second == overloaded_constructor());
x.emplace(piecewise_rvalue(), TUPLE_NAMESPACE::make_tuple(2, 3),
TUPLE_NAMESPACE::make_tuple(4, 5, 6));
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
x.find(overloaded_constructor(2, 3))->second ==
overloaded_constructor(4, 5, 6));
derived_from_piecewise_construct_t d;
x.emplace(
d, TUPLE_NAMESPACE::make_tuple(9, 3, 1), TUPLE_NAMESPACE::make_tuple(10));
BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
x.find(overloaded_constructor(9, 3, 1))->second ==
overloaded_constructor(10));
x.clear();
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
TUPLE_NAMESPACE::make_tuple(1), TUPLE_NAMESPACE::make_tuple(2, 3));
check =
std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3));
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
}
#endif
}
UNORDERED_AUTO_TEST (BOOST_PP_CAT(PIECEWISE_TEST_NAME, 2)) {
#if defined(BOOST_UNORDERED_FOA_TESTS)
static boost::unordered_flat_map<overloaded_constructor,
overloaded_constructor, boost::hash<overloaded_constructor>,
std::equal_to<overloaded_constructor>,
test::allocator1<std::pair<overloaded_constructor const,
overloaded_constructor> > >* test_pw_oc_map;
static boost::unordered_node_map<overloaded_constructor,
overloaded_constructor, boost::hash<overloaded_constructor>,
std::equal_to<overloaded_constructor>,
test::allocator1<std::pair<overloaded_constructor const,
overloaded_constructor> > >* test_pw_oc_node_map;
// clang-format off
UNORDERED_TEST(MAP_PIECEWISE_TEST, ((test_pw_oc_map)(test_pw_oc_node_map)))
// clang-format on
#else
// clang-format off
UNORDERED_TEST(MAP_PIECEWISE_TEST, ((test_pw_oc_map)))
// clang-format on
#endif
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (BOOST_PP_CAT(multimap_, PIECEWISE_TEST_NAME)) {
{
#if EMULATING_PIECEWISE_CONSTRUCTION
test::detail::disable_construction_tracking _scoped;
test::detail::disable_construction_tracking _scoped;
#endif
boost::unordered_multimap<overloaded_constructor, overloaded_constructor,
boost::hash<overloaded_constructor>,
std::equal_to<overloaded_constructor>,
test::allocator1<
std::pair<overloaded_constructor const, overloaded_constructor> > >
x;
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
BOOST_TEST(
x.find(overloaded_constructor()) != x.end() &&
x.find(overloaded_constructor())->second == overloaded_constructor());
x.emplace(convertible_to_piecewise(), TUPLE_NAMESPACE::make_tuple(1),
TUPLE_NAMESPACE::make_tuple());
BOOST_TEST(
x.find(overloaded_constructor(1)) != x.end() &&
x.find(overloaded_constructor(1))->second == overloaded_constructor());
x.emplace(piecewise_rvalue(), TUPLE_NAMESPACE::make_tuple(2, 3),
TUPLE_NAMESPACE::make_tuple(4, 5, 6));
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
x.find(overloaded_constructor(2, 3))->second ==
overloaded_constructor(4, 5, 6));
derived_from_piecewise_construct_t d;
x.emplace(d, TUPLE_NAMESPACE::make_tuple(9, 3, 1),
TUPLE_NAMESPACE::make_tuple(10));
BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
x.find(overloaded_constructor(9, 3, 1))->second ==
overloaded_constructor(10));
}
}
#endif
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<
std::pair<overloaded_constructor, overloaded_constructor> >
x;
// clang-format off
UNORDERED_TEST(SET_PIECEWISE_TEST,
((test_pair_oc_set)(test_pair_oc_node_set)))
// clang-format on
#else
boost::unordered_set<
std::pair<overloaded_constructor, overloaded_constructor> >
x;
// clang-format off
UNORDERED_TEST(SET_PIECEWISE_TEST, ((test_pair_oc_set)))
// clang-format on
#endif
std::pair<overloaded_constructor, overloaded_constructor> check;
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
x.clear();
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
TUPLE_NAMESPACE::make_tuple(1), TUPLE_NAMESPACE::make_tuple(2, 3));
check =
std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3));
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
}
#undef PIECEWISE_TEST_NAME
#undef PIECEWISE_NAMESPACE
+6 -3
View File
@@ -1,20 +1,23 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/unordered.hpp"
#ifdef BOOST_UNORDERED_FOA_TESTS
void foo(boost::unordered_flat_set<int>&, boost::unordered_flat_map<int, int>&);
void foo(boost::unordered_flat_set<int>&, boost::unordered_flat_map<int, int>&,
boost::unordered_node_set<int>&, boost::unordered_node_map<int, int>&);
int main()
{
boost::unordered_flat_set<int> x1;
boost::unordered_flat_map<int, int> x2;
boost::unordered_node_set<int> x3;
boost::unordered_node_map<int, int> x4;
foo(x1, x2);
foo(x1, x2, x3, x4);
return 0;
}
+6 -3
View File
@@ -1,14 +1,15 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/unordered.hpp"
#ifdef BOOST_UNORDERED_FOA_TESTS
void foo(
boost::unordered_flat_set<int>& x1, boost::unordered_flat_map<int, int>& x2)
void foo(boost::unordered_flat_set<int>& x1,
boost::unordered_flat_map<int, int>& x2, boost::unordered_node_set<int>& x3,
boost::unordered_node_map<int, int>& x4)
{
#if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
struct dummy
@@ -20,6 +21,8 @@ void foo(
x1.insert(1);
x2[2] = 2;
x3.insert(3);
x4.insert(std::make_pair(4, 5));
}
#else
void foo(boost::unordered_set<int>& x1, boost::unordered_map<int, int>& x2,
+8 -3
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -86,12 +86,17 @@ namespace load_factor_tests {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int>* int_set_ptr;
boost::unordered_flat_map<int, int>* int_map_ptr;
boost::unordered_node_set<int>* int_node_set_ptr;
boost::unordered_node_map<int, int>* int_node_map_ptr;
UNORDERED_TEST(set_load_factor_tests, ((int_set_ptr)(int_map_ptr)))
// clang-format off
UNORDERED_TEST(set_load_factor_tests,
((int_set_ptr)(int_map_ptr)(int_node_set_ptr)(int_node_map_ptr)))
UNORDERED_TEST(load_factor_insert_tests,
((int_set_ptr)(int_map_ptr))(
((int_set_ptr)(int_map_ptr)(int_node_set_ptr)(int_node_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#else
boost::unordered_set<int>* int_set_ptr;
boost::unordered_multiset<int>* int_multiset_ptr;
+16 -1
View File
@@ -69,9 +69,24 @@ boost::unordered_flat_map<test::object, test::object, test::hash,
test::allocator1<std::pair<test::object const, test::object> > >*
test_map_tracking;
boost::unordered_node_set<int>* int_node_set_ptr;
boost::unordered_node_map<test::movable, test::movable, test::hash,
test::equal_to, test::allocator2<test::movable> >* test_node_map_ptr;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set_tracking;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::allocator1<std::pair<test::object const, test::object> > >*
test_node_map_tracking;
// clang-format off
UNORDERED_TEST(max_load_tests,
((int_set_ptr)(test_map_ptr)(test_set_tracking)(test_map_tracking))(
((int_set_ptr)(test_map_ptr)(test_set_tracking)(test_map_tracking)
(int_node_set_ptr)(test_node_map_ptr)
(test_node_set_tracking)(test_node_map_tracking))(
(sequential)))
// clang-format on
#endif
RUN_TESTS()
+90 -17
View File
@@ -1,6 +1,6 @@
// Copyright 2016 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -16,14 +16,9 @@
namespace merge_tests {
UNORDERED_AUTO_TEST (merge_set) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> x;
boost::unordered_flat_set<int> y;
#else
boost::unordered_set<int> x;
boost::unordered_set<int> y;
#endif
template <class X> static void merge_set(X*)
{
X x, y;
x.merge(y);
BOOST_TEST(x.empty());
@@ -237,22 +232,23 @@ namespace merge_tests {
using test::generate_collisions;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int>* int_set;
boost::unordered_flat_set<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_set_std_alloc;
boost::unordered_flat_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_flat_map<test::movable, test::movable, test::hash, test::equal_to,
test::allocator2<test::movable> >* test_map;
boost::unordered_flat_map<test::movable, test::movable, test::hash,
test::equal_to, test::allocator2<test::movable> >* test_map;
// clang-format off
UNORDERED_TEST(merge_set, ((int_set)))
UNORDERED_TEST(merge_empty_test,
((test_set_std_alloc))
((test_set_std_alloc))
@@ -308,7 +304,82 @@ UNORDERED_TEST(merge_into_unique_keys_test,
((0)(1)(2))
((default_generator)(generate_collisions)))
// clang-format on
boost::unordered_node_set<int>* int_node_set;
boost::unordered_node_set<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_node_set_std_alloc;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, std::allocator<test::object> >* test_node_map_std_alloc;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set;
boost::unordered_node_map<test::movable, test::movable, test::hash,
test::equal_to, test::allocator2<test::movable> >* test_node_map;
// clang-format off
UNORDERED_TEST(merge_set, ((int_node_set)))
UNORDERED_TEST(merge_empty_test,
((test_node_set_std_alloc))
((test_node_set_std_alloc))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_empty_test,
((test_node_map_std_alloc))
((test_node_map_std_alloc))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_empty_test,
((test_node_set))
((test_node_set))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_empty_test,
((test_node_map))
((test_node_map))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_empty_test,
((test_node_set_std_alloc))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_empty_test,
((test_node_map_std_alloc))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_empty_test,
((test_node_set))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_empty_test,
((test_node_map))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_unique_keys_test,
((test_node_set_std_alloc))
((test_node_set_std_alloc))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_unique_keys_test,
((test_node_map_std_alloc))
((test_node_map_std_alloc))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_unique_keys_test,
((test_node_set))
((test_node_set))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_unique_keys_test,
((test_node_map))
((test_node_map))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
// clang-format on
#else
boost::unordered_set<int>* int_set;
boost::unordered_set<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_set_std_alloc;
boost::unordered_multiset<test::movable, test::hash, test::equal_to,
@@ -330,6 +401,8 @@ UNORDERED_TEST(merge_into_unique_keys_test,
test::equal_to, test::allocator2<test::movable> >* test_multimap;
// clang-format off
UNORDERED_TEST(merge_set, ((int_set)))
UNORDERED_TEST(merge_empty_test,
((test_set_std_alloc)(test_multiset_std_alloc))
((test_set_std_alloc)(test_multiset_std_alloc))
@@ -412,6 +485,6 @@ UNORDERED_TEST(merge_into_equiv_keys_test,
// clang-format on
#endif
}
} // namespace merge_tests
RUN_TESTS()
+55 -5
View File
@@ -1,6 +1,6 @@
// Copyright 2008-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
@@ -408,18 +408,68 @@ namespace move_tests {
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::no_propagate_move> >* test_map_no_prop_move;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
std::allocator<std::pair<test::object const, test::object> > >*
test_node_map_std_alloc;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_node_set;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::allocator1<std::pair<test::object const, test::object> > >*
test_node_map;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_node_set_prop_move;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::propagate_move> >* test_node_map_prop_move;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_node_set_no_prop_move;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::no_propagate_move> >* test_node_map_no_prop_move;
// clang-format off
UNORDERED_TEST(move_construct_tests1,
((test_map_std_alloc)(test_set)(test_map)(test_set_prop_move)(test_map_prop_move)(test_set_no_prop_move)(test_map_no_prop_move))(
((test_map_std_alloc)(test_set)(test_map)
(test_set_prop_move)(test_map_prop_move)
(test_set_no_prop_move)(test_map_no_prop_move)
(test_node_map_std_alloc)(test_node_set)(test_node_map)
(test_node_set_prop_move)(test_node_map_prop_move)
(test_node_set_no_prop_move)(test_node_map_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_assign_tests1,
((test_map_std_alloc)(test_set)(test_map)(test_set_prop_move)(test_map_prop_move)(test_set_no_prop_move)(test_map_no_prop_move))(
((test_map_std_alloc)(test_set)(test_map)
(test_set_prop_move)(test_map_prop_move)
(test_set_no_prop_move)(test_map_no_prop_move)
(test_node_map_std_alloc)(test_node_set)(test_node_map)
(test_node_set_prop_move)(test_node_map_prop_move)
(test_node_set_no_prop_move)(test_node_map_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_construct_tests2,
((test_set)(test_map)(test_set_prop_move)(test_map_prop_move)(test_set_no_prop_move)(test_map_no_prop_move))(
((test_set)(test_map)
(test_set_prop_move)(test_map_prop_move)
(test_set_no_prop_move)(test_map_no_prop_move)
(test_node_set)(test_node_map)
(test_node_set_prop_move)(test_node_map_prop_move)
(test_node_set_no_prop_move)(test_node_map_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_assign_tests2,
((test_set)(test_map)(test_set_prop_move)(test_map_prop_move)(test_set_no_prop_move)(test_map_no_prop_move))(
((test_set)(test_map)
(test_set_prop_move)(test_map_prop_move)
(test_set_no_prop_move)(test_map_no_prop_move)
(test_node_set)(test_node_map)
(test_node_set_prop_move)(test_node_map_prop_move)
(test_node_set_no_prop_move)(test_node_map_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#else
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<std::pair<test::object const, test::object> > >*
+192 -34
View File
@@ -1,12 +1,12 @@
// Copyright 2016 Daniel James.
// Copyright 2023 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/postfix.hpp"
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/unordered.hpp"
#include "../helpers/helpers.hpp"
#include "../helpers/metafunctions.hpp"
@@ -17,15 +17,19 @@
#include <set>
#include <string>
UNORDERED_AUTO_TEST (example1) {
typedef boost::unordered_map<int, std::string>::insert_return_type
insert_return_type;
template <template <class Key, class T, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map>
static void example1()
{
typedef typename Map<int, std::string>::insert_return_type insert_return_type;
boost::unordered_map<int, std::string> src;
Map<int, std::string> src;
src.emplace(1, "one");
src.emplace(2, "two");
src.emplace(3, "buckle my shoe");
boost::unordered_map<int, std::string> dst;
Map<int, std::string> dst;
dst.emplace(3, "three");
dst.insert(src.extract(src.find(1)));
@@ -42,12 +46,16 @@ UNORDERED_AUTO_TEST (example1) {
BOOST_TEST(r.node.mapped() == "buckle my shoe");
}
UNORDERED_AUTO_TEST (example2) {
boost::unordered_set<int> src;
template <template <class Key, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>, class Allocator = std::allocator<Key> >
class Set>
static void example2()
{
Set<int> src;
src.insert(1);
src.insert(3);
src.insert(5);
boost::unordered_set<int> dst;
Set<int> dst;
dst.insert(2);
dst.insert(4);
dst.insert(5);
@@ -57,14 +65,18 @@ UNORDERED_AUTO_TEST (example2) {
// dst == {1, 2, 3, 4, 5}
}
UNORDERED_AUTO_TEST (example3) {
typedef boost::unordered_set<int>::iterator iterator;
template <template <class Key, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>, class Allocator = std::allocator<Key> >
class Set>
static void example3()
{
typedef typename Set<int>::iterator iterator;
boost::unordered_set<int> src;
Set<int> src;
src.insert(1);
src.insert(3);
src.insert(5);
boost::unordered_set<int> dst;
Set<int> dst;
dst.insert(2);
dst.insert(4);
dst.insert(5);
@@ -88,16 +100,24 @@ UNORDERED_AUTO_TEST (example3) {
BOOST_TEST(it == dst2.end());
}
UNORDERED_AUTO_TEST (failed_insertion_with_hint) {
template <template <class Key, class T, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map,
template <class Key, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>, class Allocator = std::allocator<Key> >
class Set>
static void failed_insertion_with_hint()
{
{
boost::unordered_set<int> src;
boost::unordered_set<int> dst;
Set<int> src;
Set<int> dst;
src.emplace(10);
src.emplace(20);
dst.emplace(10);
dst.emplace(20);
boost::unordered_set<int>::node_type nh = src.extract(10);
typename Set<int>::node_type nh = src.extract(10);
BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh);
@@ -116,14 +136,14 @@ UNORDERED_AUTO_TEST (failed_insertion_with_hint) {
}
{
boost::unordered_map<int, int> src;
boost::unordered_map<int, int> dst;
Map<int, int> src;
Map<int, int> dst;
src.emplace(10, 30);
src.emplace(20, 5);
dst.emplace(10, 20);
dst.emplace(20, 2);
boost::unordered_map<int, int>::node_type nh = src.extract(10);
typename Map<int, int>::node_type nh = src.extract(10);
BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh);
BOOST_TEST(!nh.empty());
@@ -231,20 +251,38 @@ template <typename Container> void node_handle_tests_impl(Container& c)
BOOST_TEST(!n4);
}
UNORDERED_AUTO_TEST (node_handle_tests) {
boost::unordered_set<int> x1;
template <template <class Key, class T, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map,
template <class Key, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>, class Allocator = std::allocator<Key> >
class Set>
static void node_handle_tests()
{
Set<int> x1;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
node_handle_tests_impl(x1);
boost::unordered_map<int, std::string> x2;
Map<int, std::string> x2;
x2.emplace(10, "ten");
x2.emplace(-23, "twenty");
x2.emplace(-76, "thirty");
node_handle_tests_impl(x2);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
template <class X> typename X::iterator insert_empty_node(X& x)
{
typedef typename X::node_type node_type;
return x.insert(node_type()).position;
}
#else
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
typename boost::unordered_map<Key, T, Hash, KeyEqual, Allocator>::iterator
insert_empty_node(boost::unordered_map<Key, T, Hash, KeyEqual, Allocator>& c)
@@ -288,8 +326,10 @@ insert_empty_node(boost::unordered_multiset<T, Hash, KeyEqual, Allocator>& c)
return c.insert(node_type());
}
#endif
template <typename Container1, typename Container2>
void insert_node_handle_unique(Container1& c1, Container2& c2)
static void insert_node_handle_unique(Container1& c1, Container2& c2)
{
typedef typename Container1::node_type node_type;
typedef typename Container1::value_type value_type;
@@ -330,7 +370,7 @@ void insert_node_handle_unique(Container1& c1, Container2& c2)
}
template <typename Container1, typename Container2>
void insert_node_handle_unique2(Container1& c1, Container2& c2)
static void insert_node_handle_unique2(Container1& c1, Container2& c2)
{
typedef typename Container1::node_type node_type;
typedef typename Container1::value_type value_type;
@@ -362,6 +402,130 @@ void insert_node_handle_unique2(Container1& c1, Container2& c2)
}
}
struct hash_thing
{
std::size_t operator()(int x) const
{
return static_cast<std::size_t>(x * 13 + 5);
}
};
#ifdef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (examples) {
example1<boost::unordered_node_map>();
example2<boost::unordered_node_set>();
example3<boost::unordered_node_set>();
failed_insertion_with_hint<boost::unordered_node_map,
boost::unordered_node_set>();
node_handle_tests<boost::unordered_node_map, boost::unordered_node_set>();
}
UNORDERED_AUTO_TEST (insert_node_handle_unique_tests) {
{
boost::unordered_node_set<int> x1;
boost::unordered_node_set<int> x2;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
x2.emplace(140);
insert_node_handle_unique(x1, x2);
BOOST_TEST(x2.size() == 3);
}
{
boost::unordered_node_set<int> x1;
boost::unordered_node_set<int> x2;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
x2.emplace(140);
insert_node_handle_unique(x1, x2);
BOOST_TEST(x2.size() == 3);
}
{
boost::unordered_node_map<int, int, hash_thing> x1;
boost::unordered_node_map<int, int> x2;
x1.emplace(67, 50);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_unique(x1, x2);
BOOST_TEST(x2.size() == 4);
}
{
boost::unordered_node_map<int, int, hash_thing> x1;
boost::unordered_node_map<int, int> x2;
x1.emplace(67, 50);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_unique(x1, x2);
BOOST_TEST(x2.size() == 4);
}
}
UNORDERED_AUTO_TEST (insert_node_handle_unique_tests2) {
{
boost::unordered_node_set<int> x1;
boost::unordered_node_set<int> x2;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
x2.emplace(140);
insert_node_handle_unique2(x1, x2);
BOOST_TEST(x2.size() == 3);
}
{
boost::unordered_node_set<int> x1;
boost::unordered_node_set<int> x2;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
x2.emplace(140);
insert_node_handle_unique2(x1, x2);
BOOST_TEST(x2.size() == 3);
}
{
boost::unordered_node_map<int, int, hash_thing> x1;
boost::unordered_node_map<int, int> x2;
x1.emplace(67, 50);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_unique2(x1, x2);
BOOST_TEST(x2.size() == 4);
}
{
boost::unordered_node_map<int, int, hash_thing> x1;
boost::unordered_node_map<int, int> x2;
x1.emplace(67, 50);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_unique2(x1, x2);
BOOST_TEST(x2.size() == 4);
}
}
#else
UNORDERED_AUTO_TEST (examples) {
example1<boost::unordered_map>();
example2<boost::unordered_set>();
example3<boost::unordered_set>();
failed_insertion_with_hint<boost::unordered_map, boost::unordered_set>();
node_handle_tests<boost::unordered_map, boost::unordered_set>();
}
template <typename Container1, typename Container2>
void insert_node_handle_equiv(Container1& c1, Container2& c2)
{
@@ -389,14 +553,6 @@ void insert_node_handle_equiv(Container1& c1, Container2& c2)
}
}
struct hash_thing
{
std::size_t operator()(int x) const
{
return static_cast<std::size_t>(x * 13 + 5);
}
};
UNORDERED_AUTO_TEST (insert_node_handle_unique_tests) {
{
boost::unordered_set<int> x1;
@@ -547,4 +703,6 @@ UNORDERED_AUTO_TEST (insert_node_handle_unique_tests2) {
}
}
#endif
RUN_TESTS()
+60 -31
View File
@@ -6,8 +6,8 @@
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include "../helpers/fwd.hpp"
#include "../helpers/test.hpp"
#if defined(BOOST_MSVC)
#pragma warning(push)
@@ -203,6 +203,10 @@ namespace noexcept_tests {
boost::unordered_flat_set<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_flat_map<int, int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_node_set<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_node_map<int, int> >::value));
#else
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_set<int> >::value));
@@ -222,6 +226,13 @@ namespace noexcept_tests {
BOOST_TEST(
(!boost::is_nothrow_move_constructible<boost::unordered_flat_set<int,
boost::hash<int>, equal_to_possible_exception> >::value));
BOOST_TEST(
(!boost::is_nothrow_move_constructible<
boost::unordered_node_set<int, hash_possible_exception> >::value));
BOOST_TEST(
(!boost::is_nothrow_move_constructible<boost::unordered_node_set<int,
boost::hash<int>, equal_to_possible_exception> >::value));
#else
BOOST_TEST((!boost::is_nothrow_move_constructible<
boost::unordered_set<int, hash_possible_exception> >::value));
@@ -231,31 +242,22 @@ namespace noexcept_tests {
#endif
}
UNORDERED_AUTO_TEST (test_nothrow_move_when_noexcept) {
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int, hash_nothrow_move_construct,
equal_to_nothrow_move_construct>
throwing_set;
#else
typedef boost::unordered_set<int, hash_nothrow_move_construct,
equal_to_nothrow_move_construct>
throwing_set;
#endif
template <class X> static void test_nothrow_move_when_noexcept(X*)
{
if (have_is_nothrow_move) {
BOOST_TEST(boost::is_nothrow_move_constructible<throwing_set>::value);
BOOST_TEST(boost::is_nothrow_move_constructible<X>::value);
}
throwing_test_exception = false;
throwing_set x1;
X x1;
x1.insert(10);
x1.insert(50);
try {
throwing_test_exception = true;
throwing_set x2 = boost::move(x1);
X x2 = boost::move(x1);
BOOST_TEST(x2.size() == 2);
BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
BOOST_TEST(have_is_nothrow_move);
@@ -327,24 +329,16 @@ namespace noexcept_tests {
}
}
UNORDERED_AUTO_TEST (test_nothrow_swap_when_noexcept) {
#if BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int, hash_nothrow_swap,
equal_to_nothrow_swap>
throwing_set;
#else
typedef boost::unordered_set<int, hash_nothrow_swap, equal_to_nothrow_swap>
throwing_set;
#endif
template <class X> static void test_nothrow_swap_when_noexcept(X*)
{
if (have_is_nothrow_swap) {
BOOST_TEST(boost::is_nothrow_swappable<throwing_set>::value);
BOOST_TEST(boost::is_nothrow_swappable<X>::value);
}
throwing_test_exception = false;
throwing_set x1;
throwing_set x2;
X x1;
X x2;
x1.insert(10);
x1.insert(50);
for (int i = 0; i < 100; ++i) {
@@ -365,7 +359,7 @@ namespace noexcept_tests {
throwing_test_exception = false;
}
}
} // namespace noexcept_tests
#if defined(BOOST_MSVC)
#pragma warning(pop)
@@ -401,6 +395,7 @@ template <class T> class allocator2
{
BOOST_COPYABLE_AND_MOVABLE(allocator2)
allocator2 operator=(BOOST_COPY_ASSIGN_REF(allocator2));
public:
typedef T value_type;
typedef boost::true_type propagate_on_container_move_assignment;
@@ -431,21 +426,53 @@ UNORDERED_AUTO_TEST (prelim_allocator_checks) {
BOOST_TEST(boost::allocator_is_always_equal<allocator2<int> >::type::value);
BOOST_TEST(boost::allocator_propagate_on_container_move_assignment<
allocator2<int> >::type::value);
allocator2<int> >::type::value);
}
using test::default_generator;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int, noexcept_tests::hash_nothrow_move_construct,
noexcept_tests::equal_to_nothrow_move_construct>* throwing_set;
boost::unordered_flat_set<int, noexcept_tests::hash_nothrow_swap,
noexcept_tests::equal_to_nothrow_swap>* throwing_set2;
boost::unordered_flat_set<int, noexcept_tests::hash_nothrow_swap,
noexcept_tests::equal_to_nothrow_swap, allocator1<int> >* throwing_set_alloc1;
boost::unordered_flat_set<int, noexcept_tests::hash_nothrow_swap,
noexcept_tests::equal_to_nothrow_swap, allocator2<int> >* throwing_set_alloc2;
boost::unordered_node_set<int, noexcept_tests::hash_nothrow_move_construct,
noexcept_tests::equal_to_nothrow_move_construct>* throwing_node_set;
boost::unordered_node_set<int, noexcept_tests::hash_nothrow_swap,
noexcept_tests::equal_to_nothrow_swap>* throwing_node_set2;
boost::unordered_node_set<int, noexcept_tests::hash_nothrow_swap,
noexcept_tests::equal_to_nothrow_swap, allocator1<int> >*
throwing_node_set_alloc1;
boost::unordered_node_set<int, noexcept_tests::hash_nothrow_swap,
noexcept_tests::equal_to_nothrow_swap, allocator2<int> >*
throwing_node_set_alloc2;
// clang-format off
UNORDERED_TEST(
test_nothrow_move_when_noexcept, ((throwing_set)(throwing_node_set)))
UNORDERED_TEST(
test_nothrow_swap_when_noexcept, ((throwing_set2)(throwing_node_set2)))
UNORDERED_TEST(test_nothrow_move_assign_when_noexcept,
((throwing_set_alloc1)(throwing_set_alloc2))((default_generator)))
((throwing_set_alloc1)(throwing_set_alloc2)
(throwing_node_set_alloc1)(throwing_node_set_alloc2))(
(default_generator)))
// clang-format on
#else
boost::unordered_set<int, noexcept_tests::hash_nothrow_move_construct,
noexcept_tests::equal_to_nothrow_move_construct>* throwing_set;
boost::unordered_set<int, noexcept_tests::hash_nothrow_swap,
noexcept_tests::equal_to_nothrow_swap>* throwing_set2;
boost::unordered_set<int, noexcept_tests::hash_nothrow_move_assign,
noexcept_tests::equal_to_nothrow_move_assign, allocator1<int> >*
throwing_set_alloc1;
@@ -454,6 +481,8 @@ boost::unordered_set<int, noexcept_tests::hash_nothrow_move_assign,
noexcept_tests::equal_to_nothrow_move_assign, allocator2<int> >*
throwing_set_alloc2;
UNORDERED_TEST(test_nothrow_move_when_noexcept, ((throwing_set)))
UNORDERED_TEST(test_nothrow_swap_when_noexcept, ((throwing_set2)))
UNORDERED_TEST(test_nothrow_move_assign_when_noexcept,
((throwing_set_alloc1)(throwing_set_alloc2))((default_generator)))
#endif
+37 -2
View File
@@ -1,5 +1,5 @@
// Copyright (C) 2022 Christian Mazakas
// Copyright (C) 2022-2023 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
@@ -335,12 +335,14 @@ namespace move_tests {
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
#ifndef BOOST_UNORDERED_FOA_TESTS
template <class T> static void extract(T& y, test::random_values<T> const& v)
{
(void)y.extract(get_key(*v.begin()));
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
#endif
template <class T> static void merge(T& y, test::random_values<T> const& v)
{
@@ -375,6 +377,7 @@ namespace move_tests {
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
#ifndef BOOST_UNORDERED_FOA_TESTS
template <class T> static void buckets(T& y, test::random_values<T> const& v)
{
(void)y.begin(0);
@@ -384,6 +387,7 @@ namespace move_tests {
(void)y.bucket_size(0);
(void)y.bucket(get_key(*v.begin()));
}
#endif
template <class T>
static void double_move_construct(T& y, test::random_values<T> const&)
@@ -607,9 +611,38 @@ namespace move_tests {
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::no_propagate_move> >* test_map_no_prop_move;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_node_set;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::allocator1<std::pair<test::object const, test::object> > >*
test_node_map;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_node_set_prop_move;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::propagate_move> >* test_node_map_prop_move;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_node_set_no_prop_move;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::no_propagate_move> >* test_node_map_no_prop_move;
// clang-format off
UNORDERED_TEST(post_move_tests,
((test_set)(test_map)(test_set_prop_move)(test_map_prop_move)(test_set_no_prop_move)(test_map_no_prop_move))(
((test_set)(test_map)(test_set_prop_move)(test_map_prop_move)
(test_set_no_prop_move)(test_map_no_prop_move)
(test_node_set)(test_node_map)
(test_node_set_prop_move)(test_node_map_prop_move)
(test_node_set_no_prop_move)(test_node_map_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#else
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<std::pair<test::object const, test::object> > >*
@@ -654,12 +687,14 @@ namespace move_tests {
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::no_propagate_move> >* test_multimap_no_prop_move;
// clang-format off
UNORDERED_TEST(post_move_tests,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_move)(
test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)(
test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(
test_multimap_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#endif
}
+92 -21
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -437,6 +437,35 @@ namespace rehash_tests {
tracker.compare(x);
}
template <class X>
void rehash_node_stability(X*, test::random_generator generator)
{
typedef typename X::value_type value_type;
std::set<value_type const*> elements;
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end());
X x(v.begin(), v.end());
typedef typename X::iterator iterator;
for (iterator pos = x.begin(); pos != x.end(); ++pos) {
elements.insert(boost::addressof(*pos));
}
x.rehash(2 * x.bucket_count());
for (iterator pos = x.begin(); pos != x.end(); ++pos) {
if (!BOOST_TEST(
elements.find(boost::addressof(*pos)) != elements.end())) {
break;
}
}
tracker.compare(x);
}
template <class X> void rehash_test1(X*, test::random_generator generator)
{
test::random_values<X> v(1000, generator);
@@ -581,32 +610,67 @@ namespace rehash_tests {
monotonic_allocator<std::pair<test::object const, test::object> > >*
test_map_monotonic;
UNORDERED_TEST(rehash_empty_test1, ((int_set_ptr)(test_map_ptr)))
boost::unordered_node_set<int>* int_node_set_ptr;
boost::unordered_node_map<test::movable, test::movable, test::hash,
test::equal_to, test::allocator2<test::movable> >* test_node_map_ptr;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set_tracking;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::allocator1<std::pair<test::object const, test::object> > >*
test_node_map_tracking;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
monotonic_allocator<test::object> >* test_node_set_monotonic;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
monotonic_allocator<std::pair<test::object const, test::object> > >*
test_node_map_monotonic;
// clang-format off
UNORDERED_TEST(rehash_empty_test1,
((int_set_ptr)(test_map_ptr)
(int_node_set_ptr)(test_node_map_ptr)))
UNORDERED_TEST(rehash_empty_test2,
((int_set_ptr)(test_map_ptr))(
((int_set_ptr)(test_map_ptr)
(int_node_set_ptr)(test_node_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(rehash_empty_test3,
((int_set_ptr)(test_map_ptr))(
((int_set_ptr)(test_map_ptr)
(int_node_set_ptr)(test_node_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(rehash_test1,
((int_set_ptr)(test_map_ptr)
(int_node_set_ptr)(test_node_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(reserve_empty_test1,
((int_set_ptr)(test_map_ptr)(int_node_set_ptr)(test_node_map_ptr)))
UNORDERED_TEST(reserve_empty_test2,
((int_set_ptr)(test_map_ptr)(int_node_set_ptr)(test_node_map_ptr)))
UNORDERED_TEST(reserve_test1,
((int_set_ptr)(test_map_ptr)(int_node_set_ptr)(test_node_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(reserve_test2,
((int_set_ptr)(test_map_ptr)(int_node_set_ptr)(test_node_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
rehash_test1, ((int_set_ptr)(test_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(reserve_empty_test1, ((int_set_ptr)(test_map_ptr)))
UNORDERED_TEST(reserve_empty_test2, ((int_set_ptr)(test_map_ptr)))
UNORDERED_TEST(
reserve_test1, ((int_set_ptr)(test_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
reserve_test2, ((int_set_ptr)(test_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(rehash_empty_tracking,
((test_set_tracking)(test_map_tracking))(
((test_set_tracking)(test_map_tracking)
(test_node_set_tracking)(test_node_map_tracking))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
rehash_nonempty_tracking, ((test_set_tracking)(test_map_tracking))(
(default_generator)(limited_range)))
UNORDERED_TEST(rehash_stability, ((test_set_monotonic)(test_map_monotonic))(
(default_generator)(limited_range)))
UNORDERED_TEST(rehash_nonempty_tracking,
((test_set_tracking)(test_map_tracking)
(test_node_set_tracking)(test_node_map_tracking))(
(default_generator)(limited_range)))
UNORDERED_TEST(rehash_stability,
((test_set_monotonic)(test_map_monotonic)
(test_node_set_monotonic)(test_node_map_monotonic))(
(default_generator)(limited_range)))
UNORDERED_TEST(rehash_node_stability,
((int_node_set_ptr)(test_node_map_ptr)
(test_node_set_tracking)(test_node_map_tracking))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#else
boost::unordered_set<int>* int_set_ptr;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
@@ -639,6 +703,7 @@ namespace rehash_tests {
monotonic_allocator<std::pair<test::object const, test::object> > >*
test_multimap_monotonic;
// clang-format off
UNORDERED_TEST(rehash_empty_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)))
UNORDERED_TEST(rehash_empty_test2,
@@ -669,6 +734,12 @@ namespace rehash_tests {
UNORDERED_TEST(rehash_stability,
((test_set_monotonic)(test_multiset_monotonic)(test_map_monotonic)(test_multimap_monotonic))(
(default_generator)(limited_range)))
UNORDERED_TEST(rehash_node_stability,
((int_set_ptr)(test_map_ptr)(test_set_tracking)(test_map_tracking)
(test_multiset_ptr)(int_multimap_ptr)
(test_multiset_tracking)(test_multimap_tracking))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#endif
} // namespace rehash_tests
+82 -88
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 Christian Mazakas.
// Copyright 2021-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -45,7 +45,8 @@ template <typename T> struct A
template <class T> int A<T>::count = 0;
template <class UnorderedContainer> void bucket_count_constructor()
template <class UnorderedContainer>
void bucket_count_constructor(UnorderedContainer*)
{
BOOST_TEST_EQ(num_allocations, 0u);
BOOST_TEST_EQ(total_allocation, 0u);
@@ -64,7 +65,8 @@ template <class UnorderedContainer> void bucket_count_constructor()
num_allocations = 0;
}
template <class UnorderedContainer> void range_bucket_constructor()
template <class UnorderedContainer>
void range_bucket_constructor(UnorderedContainer*)
{
BOOST_TEST_EQ(num_allocations, 0u);
BOOST_TEST_EQ(total_allocation, 0u);
@@ -85,7 +87,7 @@ template <class UnorderedContainer> void range_bucket_constructor()
num_allocations = 0;
}
template <class UnorderedContainer> void reserve_tests()
template <class UnorderedContainer> void reserve_tests(UnorderedContainer*)
{
BOOST_TEST_EQ(num_allocations, 0u);
BOOST_TEST_EQ(total_allocation, 0u);
@@ -124,7 +126,7 @@ template <class UnorderedContainer> void reserve_tests()
num_allocations = 0;
}
template <class UnorderedContainer> void rehash_tests()
template <class UnorderedContainer> void rehash_tests(UnorderedContainer*)
{
BOOST_TEST_EQ(num_allocations, 0u);
BOOST_TEST_EQ(total_allocation, 0u);
@@ -191,89 +193,81 @@ template <class UnorderedContainer> void rehash_tests()
num_allocations = 0;
}
UNORDERED_AUTO_TEST (unordered_set_reserve) {
{
// prove Allocator invariants
// from cppref:
// Given:
// * A, an Allocator type for type T
// * B, the corresponding Allocator type for some cv-unqualified object type
// U (as obtained by rebinding A)
//
// Expression:
// A a(b)
//
// Return Type:
// Constructs `a` such that `B(a)==b` and `A(b)==a`.
// (Note: This implies that all allocators related by rebind maintain each
// other's resources, such as memory pools.)
//
//
typedef boost::allocator_rebind<A<int>, float>::type alloc_rebound;
alloc_rebound b;
A<int> a(b);
BOOST_ASSERT(alloc_rebound(a) == b);
BOOST_ASSERT(A<int>(b) == a);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int*, boost::hash<int*>,
std::equal_to<int*>, A<int*> >
unordered_set;
typedef boost::unordered_flat_map<int*, int*, boost::hash<int*>,
std::equal_to<int*>, A<std::pair<int const*, int*> > >
unordered_map;
bucket_count_constructor<unordered_set>();
bucket_count_constructor<unordered_map>();
range_bucket_constructor<unordered_set>();
range_bucket_constructor<unordered_map>();
reserve_tests<unordered_set>();
reserve_tests<unordered_map>();
rehash_tests<unordered_set>();
rehash_tests<unordered_map>();
#else
typedef boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
A<int> >
unordered_set;
typedef boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
A<int> >
unordered_multiset;
typedef boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
A<std::pair<int const, int> > >
unordered_map;
typedef boost::unordered_multimap<int, int, boost::hash<int>,
std::equal_to<int>, A<std::pair<int const, int> > >
unordered_multimap;
bucket_count_constructor<unordered_set>();
bucket_count_constructor<unordered_map>();
bucket_count_constructor<unordered_multiset>();
bucket_count_constructor<unordered_multimap>();
range_bucket_constructor<unordered_set>();
range_bucket_constructor<unordered_map>();
range_bucket_constructor<unordered_multiset>();
range_bucket_constructor<unordered_multimap>();
reserve_tests<unordered_set>();
reserve_tests<unordered_map>();
reserve_tests<unordered_multiset>();
reserve_tests<unordered_multimap>();
rehash_tests<unordered_set>();
rehash_tests<unordered_map>();
rehash_tests<unordered_multiset>();
rehash_tests<unordered_multimap>();
#endif
UNORDERED_AUTO_TEST (allocator_check) {
// prove Allocator invariants
// from cppref:
// Given:
// * A, an Allocator type for type T
// * B, the corresponding Allocator type for some cv-unqualified object type
// U (as obtained by rebinding A)
//
// Expression:
// A a(b)
//
// Return Type:
// Constructs `a` such that `B(a)==b` and `A(b)==a`.
// (Note: This implies that all allocators related by rebind maintain each
// other's resources, such as memory pools.)
//
//
typedef boost::allocator_rebind<A<int>, float>::type alloc_rebound;
alloc_rebound b;
A<int> a(b);
BOOST_ASSERT(alloc_rebound(a) == b);
BOOST_ASSERT(A<int>(b) == a);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_set<int*, boost::hash<int*>, std::equal_to<int*>,
A<int*> >* test_set;
static boost::unordered_flat_map<int*, int*, boost::hash<int*>,
std::equal_to<int*>, A<std::pair<int const*, int*> > >* test_map;
static boost::unordered_node_set<int*, boost::hash<int*>, std::equal_to<int*>,
A<int*> >* test_node_set;
static boost::unordered_node_map<int*, int*, boost::hash<int*>,
std::equal_to<int*>, A<std::pair<int const*, int*> > >* test_node_map;
// clang-format off
UNORDERED_TEST(bucket_count_constructor,
((test_set)(test_map)(test_node_set)(test_node_map)))
UNORDERED_TEST(range_bucket_constructor,
((test_set)(test_map)(test_node_set)(test_node_map)))
UNORDERED_TEST(reserve_tests,
((test_set)(test_map)(test_node_set)(test_node_map)))
UNORDERED_TEST(rehash_tests,
((test_set)(test_map)(test_node_set)(test_node_map)))
// clang-format on
#else
static boost::unordered_set<int, boost::hash<int>, std::equal_to<int>, A<int> >*
test_set;
static boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
A<int> >* test_multiset;
static boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
A<std::pair<int const, int> > >* test_map;
static boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
A<std::pair<int const, int> > >* test_multimap;
// clang-format off
UNORDERED_TEST(bucket_count_constructor,
((test_set)(test_map)(test_multiset)(test_multimap)))
UNORDERED_TEST(range_bucket_constructor,
((test_set)(test_map)(test_multiset)(test_multimap)))
UNORDERED_TEST(reserve_tests,
((test_set)(test_map)(test_multiset)(test_multimap)))
UNORDERED_TEST(rehash_tests,
((test_set)(test_map)(test_multiset)(test_multimap)))
// clang-format on
#endif
RUN_TESTS()
+3
View File
@@ -312,7 +312,10 @@ void set_scary_test()
UNORDERED_AUTO_TEST (scary_tests) {
#ifdef BOOST_UNORDERED_FOA_TESTS
map_scary_test<boost::unordered_flat_map>();
map_scary_test<boost::unordered_node_map>();
set_scary_test<boost::unordered_flat_set>();
set_scary_test<boost::unordered_node_set>();
#else
map_scary_test<boost::unordered_map>();
map_scary_test<boost::unordered_multimap>();
+22 -13
View File
@@ -1,5 +1,5 @@
// Copyright 2021-2022 Christian Mazakas.
// Copyright 2021-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -65,21 +65,12 @@ typedef std::scoped_allocator_adaptor<test::allocator<pair_type>,
test::allocator<boost::uint64_t> >
allocator_type;
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_map<const boost::uint64_t, vector_type,
boost::hash<boost::uint64_t>, std::equal_to<boost::uint64_t>, allocator_type>
map_type;
#else
typedef boost::unordered_map<const boost::uint64_t, vector_type,
boost::hash<boost::uint64_t>, std::equal_to<boost::uint64_t>, allocator_type>
map_type;
#endif
UNORDERED_AUTO_TEST (scoped_allocator) {
template <class X> static void scoped_allocator(X*)
{
allocator_type alloc(
test::allocator<pair_type>(1337), test::allocator<boost::uint64_t>(7331));
map_type map(alloc);
X map(alloc);
for (unsigned i = 0; i < 10; ++i) {
boost::ignore_unused(map[i]);
@@ -88,6 +79,24 @@ UNORDERED_AUTO_TEST (scoped_allocator) {
BOOST_TEST(map.size() == 10);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_map<const boost::uint64_t, vector_type,
boost::hash<boost::uint64_t>, std::equal_to<boost::uint64_t>, allocator_type>*
test_map;
static boost::unordered_node_map<const boost::uint64_t, vector_type,
boost::hash<boost::uint64_t>, std::equal_to<boost::uint64_t>, allocator_type>*
test_node_map;
UNORDERED_TEST(scoped_allocator, ((test_map)(test_node_map)))
#else
static boost::unordered_map<const boost::uint64_t, vector_type,
boost::hash<boost::uint64_t>, std::equal_to<boost::uint64_t>, allocator_type>*
test_map;
UNORDERED_TEST(scoped_allocator, ((test_map)))
#endif
RUN_TESTS()
#endif
+56 -36
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -8,10 +8,13 @@
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include <cstdlib>
#include <algorithm>
#include "../helpers/equivalent.hpp"
#include "../helpers/generators.hpp"
#include "../helpers/test.hpp"
#include <algorithm>
#include <cstdlib>
test::seed_t initialize_seed(14878);
template <class X> void simple_test(X const& a)
{
@@ -84,59 +87,76 @@ template <class X> void simple_test(X const& a)
}
}
UNORDERED_AUTO_TEST (simple_tests) {
using namespace std;
srand(14878);
template <class X> static void simple_set_tests(X*)
{
X x;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> set;
#else
boost::unordered_set<int> set;
#endif
simple_test(set);
simple_test(x);
set.insert(1);
set.insert(2);
set.insert(1456);
simple_test(set);
x.insert(1);
x.insert(2);
x.insert(1456);
simple_test(x);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<int> multiset;
simple_test(multiset);
template <class X> static void simple_multiset_tests(X*)
{
X x;
simple_test(x);
for (int i1 = 0; i1 < 1000; ++i1) {
int count = rand() % 10, index = rand();
for (int j = 0; j < count; ++j)
multiset.insert(index);
x.insert(index);
}
simple_test(multiset);
simple_test(x);
}
#endif
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<int, int> map;
#else
boost::unordered_map<int, int> map;
#endif
template <class X> static void simple_map_tests(X*)
{
X x;
for (int i2 = 0; i2 < 1000; ++i2) {
map.insert(std::pair<const int, int>(rand(), rand()));
x.insert(std::pair<const int, int>(rand(), rand()));
}
simple_test(map);
simple_test(x);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
boost::unordered_multimap<int, int> multimap;
template <class X> static void simple_multimap_tests(X*)
{
X x;
for (int i3 = 0; i3 < 1000; ++i3) {
int count = rand() % 10, index = rand();
for (int j = 0; j < count; ++j)
multimap.insert(std::pair<const int, int>(index, rand()));
x.insert(std::pair<const int, int>(index, rand()));
}
simple_test(multimap);
#endif
simple_test(x);
}
#endif
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_set<int>* flat_set;
static boost::unordered_flat_map<int, int>* flat_map;
static boost::unordered_node_set<int>* node_set;
static boost::unordered_node_map<int, int>* node_map;
UNORDERED_TEST(simple_map_tests, ((flat_map)(node_map)))
UNORDERED_TEST(simple_set_tests, ((flat_set)(node_set)))
#else
static boost::unordered_set<int>* set;
static boost::unordered_map<int, int>* map;
static boost::unordered_multiset<int>* multiset;
static boost::unordered_multimap<int, int>* multimap;
UNORDERED_TEST(simple_set_tests, ((set)))
UNORDERED_TEST(simple_map_tests, ((map)))
UNORDERED_TEST(simple_multiset_tests, ((multiset)))
UNORDERED_TEST(simple_multimap_tests, ((multimap)))
#endif
RUN_TESTS()
+42 -3
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -168,19 +168,58 @@ namespace swap_tests {
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_map_no_prop_swap;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, std::allocator<test::object> >* test_node_map_std_alloc;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_node_map;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_swap> >*
test_node_set_prop_swap;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::propagate_swap> >*
test_node_map_prop_swap;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_node_set_no_prop_swap;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_node_map_no_prop_swap;
UNORDERED_AUTO_TEST (check_traits) {
BOOST_TEST(!is_propagate(test_set));
BOOST_TEST(is_propagate(test_set_prop_swap));
BOOST_TEST(!is_propagate(test_set_no_prop_swap));
BOOST_TEST(!is_propagate(test_node_set));
BOOST_TEST(is_propagate(test_node_set_prop_swap));
BOOST_TEST(!is_propagate(test_node_set_no_prop_swap));
}
// clang-format off
UNORDERED_TEST(swap_tests1,
((test_map_std_alloc)(test_set)(test_map)(test_set_prop_swap)(test_map_prop_swap)(test_set_no_prop_swap)(test_map_no_prop_swap))(
((test_map_std_alloc)(test_set)(test_map)
(test_set_prop_swap)(test_map_prop_swap)
(test_set_no_prop_swap)(test_map_no_prop_swap)
(test_node_map_std_alloc)(test_node_set)(test_node_map)
(test_node_set_prop_swap)(test_node_map_prop_swap)
(test_node_set_no_prop_swap)(test_node_map_no_prop_swap))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(swap_tests2,
((test_set)(test_map)(test_set_prop_swap)(test_map_prop_swap)(test_set_no_prop_swap)(test_map_no_prop_swap))(
((test_set)(test_map)
(test_set_prop_swap)(test_map_prop_swap)
(test_set_no_prop_swap)(test_map_no_prop_swap)
(test_node_set)(test_node_map)
(test_node_set_prop_swap)(test_node_map_prop_swap)
(test_node_set_no_prop_swap)(test_node_map_no_prop_swap))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#else
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
+326 -285
View File
@@ -64,7 +64,7 @@ struct key_equal
void count_reset() { key::count_ = 0; }
template <class UnorderedMap> void test_map_transparent_count()
template <class UnorderedMap> void test_map_transparent_count(UnorderedMap*)
{
count_reset();
@@ -92,7 +92,7 @@ template <class UnorderedMap> void test_map_transparent_count()
BOOST_TEST_EQ(key::count_, expected_key_count);
}
template <class UnorderedMap> void test_map_non_transparent_count()
template <class UnorderedMap> void test_map_non_transparent_count(UnorderedMap*)
{
count_reset();
@@ -126,7 +126,7 @@ template <class UnorderedMap> void test_map_non_transparent_count()
BOOST_TEST_EQ(key::count_, key_count);
}
template <class UnorderedSet> void test_set_transparent_count()
template <class UnorderedSet> void test_set_transparent_count(UnorderedSet*)
{
count_reset();
@@ -154,7 +154,7 @@ template <class UnorderedSet> void test_set_transparent_count()
BOOST_TEST_EQ(key::count_, expected_key_count);
}
template <class UnorderedSet> void test_set_non_transparent_count()
template <class UnorderedSet> void test_set_non_transparent_count(UnorderedSet*)
{
count_reset();
@@ -188,7 +188,7 @@ template <class UnorderedSet> void test_set_non_transparent_count()
BOOST_TEST_EQ(key::count_, key_count);
}
template <class UnorderedMap> void test_map_transparent_find()
template <class UnorderedMap> void test_map_transparent_find(UnorderedMap*)
{
count_reset();
@@ -249,7 +249,7 @@ template <class UnorderedMap> void test_map_transparent_find()
}
}
template <class UnorderedMap> void test_map_non_transparent_find()
template <class UnorderedMap> void test_map_non_transparent_find(UnorderedMap*)
{
count_reset();
@@ -310,7 +310,7 @@ template <class UnorderedMap> void test_map_non_transparent_find()
}
}
template <class UnorderedSet> void test_set_transparent_find()
template <class UnorderedSet> void test_set_transparent_find(UnorderedSet*)
{
count_reset();
@@ -362,7 +362,7 @@ template <class UnorderedSet> void test_set_transparent_find()
}
}
template <class UnorderedSet> void test_set_non_transparent_find()
template <class UnorderedSet> void test_set_non_transparent_find(UnorderedSet*)
{
count_reset();
@@ -422,7 +422,8 @@ template <class UnorderedSet> void test_set_non_transparent_find()
}
}
template <class UnorderedMap> void test_map_transparent_equal_range()
template <class UnorderedMap>
void test_map_transparent_equal_range(UnorderedMap*)
{
count_reset();
@@ -576,7 +577,8 @@ template <class UnorderedMap> void test_map_transparent_equal_range()
}
}
template <class UnorderedMap> void test_map_non_transparent_equal_range()
template <class UnorderedMap>
void test_map_non_transparent_equal_range(UnorderedMap*)
{
count_reset();
@@ -731,7 +733,8 @@ template <class UnorderedMap> void test_map_non_transparent_equal_range()
}
}
template <class UnorderedSet> void test_set_transparent_equal_range()
template <class UnorderedSet>
void test_set_transparent_equal_range(UnorderedSet*)
{
count_reset();
@@ -881,7 +884,8 @@ template <class UnorderedSet> void test_set_transparent_equal_range()
}
}
template <class UnorderedSet> void test_set_non_transparent_equal_range()
template <class UnorderedSet>
void test_set_non_transparent_equal_range(UnorderedSet*)
{
count_reset();
@@ -1114,7 +1118,7 @@ multimap_erase_const_overload_compile_test()
}
#endif
template <class UnorderedMap> void test_map_transparent_erase()
template <class UnorderedMap> void test_map_transparent_erase(UnorderedMap*)
{
count_reset();
@@ -1156,7 +1160,7 @@ template <class UnorderedMap> void test_map_transparent_erase()
BOOST_TEST_EQ(key::count_, expected_key_count);
}
template <class UnorderedMap> void test_map_non_transparent_erase()
template <class UnorderedMap> void test_map_non_transparent_erase(UnorderedMap*)
{
count_reset();
@@ -1271,7 +1275,7 @@ multiset_erase_const_overload_compile_test()
}
#endif
template <class UnorderedSet> void test_set_transparent_erase()
template <class UnorderedSet> void test_set_transparent_erase(UnorderedSet*)
{
count_reset();
@@ -1313,7 +1317,7 @@ template <class UnorderedSet> void test_set_transparent_erase()
BOOST_TEST_EQ(key::count_, expected_key_count);
}
template <class UnorderedSet> void test_set_non_transparent_erase()
template <class UnorderedSet> void test_set_non_transparent_erase(UnorderedSet*)
{
count_reset();
@@ -1391,9 +1395,8 @@ multimap_extract_const_overload_compile_test()
}
#endif
template <class UnorderedMap> void test_map_transparent_extract()
template <class UnorderedMap> void test_map_transparent_extract(UnorderedMap*)
{
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename UnorderedMap::node_type node_type;
typedef typename UnorderedMap::const_iterator const_iterator;
typedef std::pair<const_iterator, const_iterator> const_iterator_pair;
@@ -1429,12 +1432,11 @@ template <class UnorderedMap> void test_map_transparent_extract()
BOOST_TEST(nh.empty());
BOOST_TEST_EQ(key::count_, expected_key_count);
#endif
}
template <class UnorderedMap> void test_map_non_transparent_extract()
template <class UnorderedMap>
void test_map_non_transparent_extract(UnorderedMap*)
{
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename UnorderedMap::node_type node_type;
typedef typename UnorderedMap::const_iterator const_iterator;
typedef std::pair<const_iterator, const_iterator> const_iterator_pair;
@@ -1475,10 +1477,10 @@ template <class UnorderedMap> void test_map_non_transparent_extract()
++key_count;
BOOST_TEST(nh.empty());
BOOST_TEST_EQ(key::count_, key_count);
#endif
}
template <class UnorderedMap> void test_map_transparent_try_emplace()
template <class UnorderedMap>
void test_map_transparent_try_emplace(UnorderedMap*)
{
count_reset();
@@ -1516,7 +1518,8 @@ template <class UnorderedMap> void test_map_transparent_try_emplace()
BOOST_TEST_EQ(key::count_, key_count + 1);
}
template <class UnorderedMap> void test_map_non_transparent_try_emplace()
template <class UnorderedMap>
void test_map_non_transparent_try_emplace(UnorderedMap*)
{
count_reset();
@@ -1555,7 +1558,8 @@ template <class UnorderedMap> void test_map_non_transparent_try_emplace()
BOOST_TEST(p == map.find(5));
}
template <class UnorderedMap> void test_map_transparent_insert_or_assign()
template <class UnorderedMap>
void test_map_transparent_insert_or_assign(UnorderedMap*)
{
count_reset();
@@ -1595,7 +1599,8 @@ template <class UnorderedMap> void test_map_transparent_insert_or_assign()
BOOST_TEST_EQ(key::count_, key_count + 1);
}
template <class UnorderedMap> void test_map_non_transparent_insert_or_assign()
template <class UnorderedMap>
void test_map_non_transparent_insert_or_assign(UnorderedMap*)
{
count_reset();
@@ -1636,7 +1641,7 @@ template <class UnorderedMap> void test_map_non_transparent_insert_or_assign()
BOOST_TEST(p == map.find(5));
}
template <class UnorderedMap> void test_map_transparent_subscript()
template <class UnorderedMap> void test_map_transparent_subscript(UnorderedMap*)
{
count_reset();
@@ -1658,7 +1663,8 @@ template <class UnorderedMap> void test_map_transparent_subscript()
BOOST_TEST_EQ(key::count_, key_count + 1);
}
template <class UnorderedMap> void test_map_non_transparent_subscript()
template <class UnorderedMap>
void test_map_non_transparent_subscript(UnorderedMap*)
{
count_reset();
@@ -1681,7 +1687,7 @@ template <class UnorderedMap> void test_map_non_transparent_subscript()
BOOST_TEST_EQ(key::count_, key_count + 2);
}
template <class UnorderedMap> void test_map_transparent_at()
template <class UnorderedMap> void test_map_transparent_at(UnorderedMap*)
{
count_reset();
@@ -1710,7 +1716,7 @@ template <class UnorderedMap> void test_map_transparent_at()
BOOST_TEST_EQ(key::count_, key_count);
}
template <class UnorderedMap> void test_map_non_transparent_at()
template <class UnorderedMap> void test_map_non_transparent_at(UnorderedMap*)
{
count_reset();
@@ -1742,7 +1748,7 @@ template <class UnorderedMap> void test_map_non_transparent_at()
BOOST_TEST_EQ(key::count_, key_count + 1);
}
template <class UnorderedMap> void test_map_transparent_bucket()
template <class UnorderedMap> void test_map_transparent_bucket(UnorderedMap*)
{
#ifndef BOOST_UNORDERED_FOA_TESTS
count_reset();
@@ -1763,7 +1769,8 @@ template <class UnorderedMap> void test_map_transparent_bucket()
#endif
}
template <class UnorderedMap> void test_map_non_transparent_bucket()
template <class UnorderedMap>
void test_map_non_transparent_bucket(UnorderedMap*)
{
#ifndef BOOST_UNORDERED_FOA_TESTS
count_reset();
@@ -1824,7 +1831,7 @@ multiset_extract_const_overload_compile_test()
}
#endif
template <class UnorderedSet> void test_set_transparent_extract()
template <class UnorderedSet> void test_set_transparent_extract(UnorderedSet*)
{
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename UnorderedSet::node_type node_type;
@@ -1873,9 +1880,9 @@ template <class UnorderedSet> void test_set_transparent_extract()
#endif
}
template <class UnorderedSet> void test_set_non_transparent_extract()
template <class UnorderedSet>
void test_set_non_transparent_extract(UnorderedSet*)
{
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename UnorderedSet::node_type node_type;
count_reset();
@@ -1929,10 +1936,9 @@ template <class UnorderedSet> void test_set_non_transparent_extract()
BOOST_TEST_EQ(set.size(), set_size);
BOOST_TEST_EQ(key::count_, key_count);
#endif
}
template <class UnorderedSet> void test_set_transparent_bucket()
template <class UnorderedSet> void test_set_transparent_bucket(UnorderedSet*)
{
#ifndef BOOST_UNORDERED_FOA_TESTS
count_reset();
@@ -1953,7 +1959,8 @@ template <class UnorderedSet> void test_set_transparent_bucket()
#endif
}
template <class UnorderedSet> void test_set_non_transparent_bucket()
template <class UnorderedSet>
void test_set_non_transparent_bucket(UnorderedSet*)
{
#ifndef BOOST_UNORDERED_FOA_TESTS
count_reset();
@@ -1974,7 +1981,7 @@ template <class UnorderedSet> void test_set_non_transparent_bucket()
#endif
}
template <class UnorderedSet> void test_set_transparent_insert()
template <class UnorderedSet> void test_set_transparent_insert(UnorderedSet*)
{
count_reset();
@@ -2019,7 +2026,8 @@ template <class UnorderedSet> void test_set_transparent_insert()
set.insert(set.begin(), set.end());
}
template <class UnorderedSet> void test_set_non_transparent_insert()
template <class UnorderedSet>
void test_set_non_transparent_insert(UnorderedSet*)
{
count_reset();
@@ -2069,272 +2077,305 @@ template <class Key, class T, class Hash, class KeyEqual> struct map_type
#endif
};
void test_unordered_map()
{
{
typedef map_type<key, int, transparent_hasher, transparent_key_equal>::type
unordered_map;
test_map_transparent_count<unordered_map>();
test_map_transparent_find<unordered_map>();
test_map_transparent_equal_range<unordered_map>();
test_map_transparent_erase<unordered_map>();
test_map_transparent_extract<unordered_map>();
test_map_transparent_try_emplace<unordered_map>();
test_map_transparent_insert_or_assign<unordered_map>();
test_map_transparent_subscript<unordered_map>();
test_map_transparent_at<unordered_map>();
test_map_transparent_bucket<unordered_map>();
}
{
// non-transparent Hash, non-transparent KeyEqual
//
typedef map_type<key, int, hasher, key_equal>::type unordered_map;
test_map_non_transparent_count<unordered_map>();
test_map_non_transparent_find<unordered_map>();
test_map_non_transparent_equal_range<unordered_map>();
test_map_non_transparent_erase<unordered_map>();
test_map_non_transparent_extract<unordered_map>();
test_map_non_transparent_try_emplace<unordered_map>();
test_map_non_transparent_insert_or_assign<unordered_map>();
test_map_non_transparent_subscript<unordered_map>();
test_map_non_transparent_at<unordered_map>();
test_map_non_transparent_bucket<unordered_map>();
}
{
// transparent Hash, non-transparent KeyEqual
//
typedef map_type<key, int, transparent_hasher, key_equal>::type
unordered_map;
test_map_non_transparent_count<unordered_map>();
test_map_non_transparent_find<unordered_map>();
test_map_non_transparent_equal_range<unordered_map>();
test_map_non_transparent_erase<unordered_map>();
test_map_non_transparent_extract<unordered_map>();
test_map_non_transparent_try_emplace<unordered_map>();
test_map_non_transparent_insert_or_assign<unordered_map>();
test_map_non_transparent_subscript<unordered_map>();
test_map_non_transparent_at<unordered_map>();
test_map_non_transparent_bucket<unordered_map>();
}
{
// non-transparent Hash, transparent KeyEqual
//
typedef map_type<key, int, hasher, transparent_key_equal>::type
unordered_map;
test_map_non_transparent_count<unordered_map>();
test_map_non_transparent_find<unordered_map>();
test_map_non_transparent_equal_range<unordered_map>();
test_map_non_transparent_erase<unordered_map>();
test_map_non_transparent_extract<unordered_map>();
test_map_non_transparent_try_emplace<unordered_map>();
test_map_non_transparent_insert_or_assign<unordered_map>();
test_map_non_transparent_subscript<unordered_map>();
test_map_non_transparent_at<unordered_map>();
test_map_non_transparent_bucket<unordered_map>();
}
}
#ifndef BOOST_UNORDERED_FOA_TESTS
void test_unordered_multimap()
{
{
typedef boost::unordered_multimap<key, int, transparent_hasher,
transparent_key_equal>
unordered_multimap;
test_map_transparent_count<unordered_multimap>();
test_map_transparent_find<unordered_multimap>();
test_map_transparent_equal_range<unordered_multimap>();
test_map_transparent_erase<unordered_multimap>();
test_map_transparent_extract<unordered_multimap>();
test_map_transparent_bucket<unordered_multimap>();
}
{
// non-transparent Hash, non-transparent KeyEqual
//
typedef boost::unordered_multimap<key, int, hasher, key_equal>
unordered_multimap;
test_map_non_transparent_count<unordered_multimap>();
test_map_non_transparent_find<unordered_multimap>();
test_map_non_transparent_equal_range<unordered_multimap>();
test_map_non_transparent_erase<unordered_multimap>();
test_map_non_transparent_extract<unordered_multimap>();
test_map_non_transparent_bucket<unordered_multimap>();
}
{
// transparent Hash, non-transparent KeyEqual
//
typedef boost::unordered_multimap<key, int, transparent_hasher, key_equal>
unordered_multimap;
test_map_non_transparent_count<unordered_multimap>();
test_map_non_transparent_find<unordered_multimap>();
test_map_non_transparent_equal_range<unordered_multimap>();
test_map_non_transparent_erase<unordered_multimap>();
test_map_non_transparent_extract<unordered_multimap>();
test_map_non_transparent_bucket<unordered_multimap>();
}
{
// non-transparent Hash, transparent KeyEqual
//
typedef boost::unordered_multimap<key, int, hasher, transparent_key_equal>
unordered_multimap;
test_map_non_transparent_count<unordered_multimap>();
test_map_non_transparent_find<unordered_multimap>();
test_map_non_transparent_equal_range<unordered_multimap>();
test_map_non_transparent_erase<unordered_multimap>();
test_map_non_transparent_extract<unordered_multimap>();
test_map_non_transparent_bucket<unordered_multimap>();
}
}
#endif
template <class Key, class Hash, class KeyEqual> struct set_type
{
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<Key, Hash, KeyEqual> type;
static boost::unordered_flat_map<key, int, transparent_hasher,
transparent_key_equal>* test_trans_map;
static boost::unordered_flat_map<key, int, hasher, key_equal>* test_map1;
static boost::unordered_flat_map<key, int, transparent_hasher, key_equal>*
test_map2;
static boost::unordered_flat_map<key, int, hasher, transparent_key_equal>*
test_map3;
static boost::unordered_node_map<key, int, transparent_hasher,
transparent_key_equal>* test_trans_node_map;
static boost::unordered_node_map<key, int, hasher, key_equal>* test_node_map1;
static boost::unordered_node_map<key, int, transparent_hasher, key_equal>*
test_node_map2;
static boost::unordered_node_map<key, int, hasher, transparent_key_equal>*
test_node_map3;
// clang-format off
UNORDERED_TEST(test_map_transparent_count,
((test_trans_map)(test_trans_node_map)))
UNORDERED_TEST(test_map_transparent_find,
((test_trans_map)(test_trans_node_map)))
UNORDERED_TEST(test_map_transparent_equal_range,
((test_trans_map)(test_trans_node_map)))
UNORDERED_TEST(test_map_transparent_erase,
((test_trans_map)(test_trans_node_map)))
UNORDERED_TEST(test_map_transparent_extract,
((test_trans_node_map)))
UNORDERED_TEST(test_map_transparent_try_emplace,
((test_trans_map)(test_trans_node_map)))
UNORDERED_TEST(test_map_transparent_insert_or_assign,
((test_trans_map)(test_trans_node_map)))
UNORDERED_TEST(test_map_transparent_subscript,
((test_trans_map)(test_trans_node_map)))
UNORDERED_TEST(test_map_transparent_at,
((test_trans_map)(test_trans_node_map)))
UNORDERED_TEST(test_map_transparent_bucket,
((test_trans_map)(test_trans_node_map)))
UNORDERED_TEST(test_map_non_transparent_count,
((test_map1)(test_map2)(test_map3)
(test_node_map1)(test_node_map2)(test_node_map3)))
UNORDERED_TEST(test_map_non_transparent_find,
((test_map1)(test_map2)(test_map3)
(test_node_map1)(test_node_map2)(test_node_map3)))
UNORDERED_TEST(test_map_non_transparent_equal_range,
((test_map1)(test_map2)(test_map3)
(test_node_map1)(test_node_map2)(test_node_map3)))
UNORDERED_TEST(test_map_non_transparent_erase,
((test_map1)(test_map2)(test_map3)
(test_node_map1)(test_node_map2)(test_node_map3)))
UNORDERED_TEST(test_map_non_transparent_extract,
((test_node_map1)(test_node_map2)(test_node_map3)))
UNORDERED_TEST(test_map_non_transparent_try_emplace,
((test_map1)(test_map2)(test_map3)
(test_node_map1)(test_node_map2)(test_node_map3)))
UNORDERED_TEST(test_map_non_transparent_insert_or_assign,
((test_map1)(test_map2)(test_map3)
(test_node_map1)(test_node_map2)(test_node_map3)))
UNORDERED_TEST(test_map_non_transparent_subscript,
((test_map1)(test_map2)(test_map3)
(test_node_map1)(test_node_map2)(test_node_map3)))
UNORDERED_TEST(test_map_non_transparent_at,
((test_map1)(test_map2)(test_map3)
(test_node_map1)(test_node_map2)(test_node_map3)))
UNORDERED_TEST(test_map_non_transparent_bucket,
((test_map1)(test_map2)(test_map3)
(test_node_map1)(test_node_map2)(test_node_map3)))
// clang-format on
#else
typedef boost::unordered_set<Key, Hash, KeyEqual> type;
#endif
};
static boost::unordered_map<key, int, transparent_hasher,
transparent_key_equal>* test_trans_map;
static boost::unordered_map<key, int, hasher, key_equal>* test_map1;
static boost::unordered_map<key, int, transparent_hasher, key_equal>* test_map2;
static boost::unordered_map<key, int, hasher, transparent_key_equal>* test_map3;
void test_unordered_set()
{
{
typedef set_type<key, transparent_hasher, transparent_key_equal>::type
unordered_set;
static boost::unordered_multimap<key, int, transparent_hasher,
transparent_key_equal>* test_trans_multimap;
static boost::unordered_multimap<key, int, hasher, key_equal>* test_multimap1;
static boost::unordered_multimap<key, int, transparent_hasher, key_equal>*
test_multimap2;
static boost::unordered_multimap<key, int, hasher, transparent_key_equal>*
test_multimap3;
test_set_transparent_count<unordered_set>();
test_set_transparent_find<unordered_set>();
test_set_transparent_erase<unordered_set>();
test_set_transparent_equal_range<unordered_set>();
test_set_transparent_extract<unordered_set>();
test_set_transparent_bucket<unordered_set>();
test_set_transparent_insert<unordered_set>();
}
// clang-format off
UNORDERED_TEST(test_map_transparent_count,
((test_trans_map)(test_trans_multimap)))
{
// non-transparent Hash, non-transparent KeyEqual
//
typedef set_type<key, hasher, key_equal>::type unordered_set;
UNORDERED_TEST(test_map_transparent_find,
((test_trans_map)(test_trans_multimap)))
test_set_non_transparent_count<unordered_set>();
test_set_non_transparent_find<unordered_set>();
test_set_non_transparent_erase<unordered_set>();
test_set_non_transparent_equal_range<unordered_set>();
test_set_non_transparent_extract<unordered_set>();
test_set_non_transparent_bucket<unordered_set>();
test_set_non_transparent_insert<unordered_set>();
}
UNORDERED_TEST(test_map_transparent_equal_range,
((test_trans_map)(test_trans_multimap)))
{
// transparent Hash, non-transparent KeyEqual
//
typedef set_type<key, transparent_hasher, key_equal>::type unordered_set;
UNORDERED_TEST(test_map_transparent_erase,
((test_trans_map)(test_trans_multimap)))
test_set_non_transparent_count<unordered_set>();
test_set_non_transparent_find<unordered_set>();
test_set_non_transparent_erase<unordered_set>();
test_set_non_transparent_equal_range<unordered_set>();
test_set_non_transparent_extract<unordered_set>();
test_set_non_transparent_bucket<unordered_set>();
test_set_non_transparent_insert<unordered_set>();
}
UNORDERED_TEST(test_map_transparent_extract,
((test_trans_map)(test_trans_multimap)))
{
// non-transparent Hash, transparent KeyEqual
//
typedef set_type<key, hasher, transparent_key_equal>::type unordered_set;
UNORDERED_TEST(test_map_transparent_try_emplace,
((test_trans_map)))
test_set_non_transparent_count<unordered_set>();
test_set_non_transparent_find<unordered_set>();
test_set_non_transparent_erase<unordered_set>();
test_set_non_transparent_equal_range<unordered_set>();
test_set_non_transparent_extract<unordered_set>();
test_set_non_transparent_bucket<unordered_set>();
test_set_non_transparent_insert<unordered_set>();
}
}
UNORDERED_TEST(test_map_transparent_insert_or_assign,
((test_trans_map)))
#ifndef BOOST_UNORDERED_FOA_TESTS
void test_unordered_multiset()
{
{
typedef boost::unordered_multiset<key, transparent_hasher,
transparent_key_equal>
unordered_set;
UNORDERED_TEST(test_map_transparent_subscript,
((test_trans_map)))
test_set_transparent_count<unordered_set>();
test_set_transparent_find<unordered_set>();
test_set_transparent_erase<unordered_set>();
test_set_transparent_equal_range<unordered_set>();
test_set_transparent_extract<unordered_set>();
test_set_transparent_bucket<unordered_set>();
}
UNORDERED_TEST(test_map_transparent_at,
((test_trans_map)))
{
// non-transparent Hash, non-transparent KeyEqual
//
typedef boost::unordered_multiset<key, hasher, key_equal> unordered_set;
UNORDERED_TEST(test_map_transparent_bucket,
((test_trans_map)(test_trans_multimap)))
test_set_non_transparent_count<unordered_set>();
test_set_non_transparent_find<unordered_set>();
test_set_non_transparent_erase<unordered_set>();
test_set_non_transparent_equal_range<unordered_set>();
test_set_non_transparent_extract<unordered_set>();
test_set_non_transparent_bucket<unordered_set>();
}
UNORDERED_TEST(test_map_non_transparent_count,
((test_map1)(test_map2)(test_map3)
(test_multimap1)(test_multimap2)(test_multimap3)))
{
// transparent Hash, non-transparent KeyEqual
//
typedef boost::unordered_multiset<key, transparent_hasher, key_equal>
unordered_set;
UNORDERED_TEST(test_map_non_transparent_find,
((test_map1)(test_map2)(test_map3)
(test_multimap1)(test_multimap2)(test_multimap3)))
test_set_non_transparent_count<unordered_set>();
test_set_non_transparent_find<unordered_set>();
test_set_non_transparent_erase<unordered_set>();
test_set_non_transparent_equal_range<unordered_set>();
test_set_non_transparent_extract<unordered_set>();
test_set_non_transparent_bucket<unordered_set>();
}
UNORDERED_TEST(test_map_non_transparent_equal_range,
((test_map1)(test_map2)(test_map3)
(test_multimap1)(test_multimap2)(test_multimap3)))
{
// non-transparent Hash, transparent KeyEqual
//
typedef boost::unordered_multiset<key, hasher, transparent_key_equal>
unordered_set;
UNORDERED_TEST(test_map_non_transparent_erase,
((test_map1)(test_map2)(test_map3)
(test_multimap1)(test_multimap2)(test_multimap3)))
test_set_non_transparent_count<unordered_set>();
test_set_non_transparent_find<unordered_set>();
test_set_non_transparent_erase<unordered_set>();
test_set_non_transparent_equal_range<unordered_set>();
test_set_non_transparent_extract<unordered_set>();
test_set_non_transparent_bucket<unordered_set>();
}
}
UNORDERED_TEST(test_map_non_transparent_extract,
((test_map1)(test_map2)(test_map3)
(test_multimap1)(test_multimap2)(test_multimap3)))
UNORDERED_TEST(test_map_non_transparent_try_emplace,
((test_map1)(test_map2)(test_map3)))
UNORDERED_TEST(test_map_non_transparent_insert_or_assign,
((test_map1)(test_map2)(test_map3)))
UNORDERED_TEST(test_map_non_transparent_subscript,
((test_map1)(test_map2)(test_map3)))
UNORDERED_TEST(test_map_non_transparent_at,
((test_map1)(test_map2)(test_map3)))
UNORDERED_TEST(test_map_non_transparent_bucket,
((test_map1)(test_map2)(test_map3)
(test_multimap1)(test_multimap2)(test_multimap3)))
// clang-format on
#endif
UNORDERED_AUTO_TEST (transparent_ops) {
test_unordered_map();
test_unordered_set();
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_set<key, transparent_hasher,
transparent_key_equal>* test_trans_set;
static boost::unordered_node_set<key, transparent_hasher,
transparent_key_equal>* test_trans_node_set;
#ifndef BOOST_UNORDERED_FOA_TESTS
test_unordered_multimap();
test_unordered_multiset();
static boost::unordered_flat_set<key, hasher, key_equal>* test_set1;
static boost::unordered_flat_set<key, transparent_hasher, key_equal>* test_set2;
static boost::unordered_flat_set<key, hasher, transparent_key_equal>* test_set3;
static boost::unordered_node_set<key, hasher, key_equal>* test_node_set1;
static boost::unordered_node_set<key, transparent_hasher, key_equal>*
test_node_set2;
static boost::unordered_node_set<key, hasher, transparent_key_equal>*
test_node_set3;
// clang-format off
UNORDERED_TEST(test_set_transparent_count,
((test_trans_set)(test_trans_node_set)))
UNORDERED_TEST(test_set_transparent_find,
((test_trans_set)(test_trans_node_set)))
UNORDERED_TEST(test_set_transparent_erase,
((test_trans_set)(test_trans_node_set)))
UNORDERED_TEST(test_set_transparent_equal_range,
((test_trans_set)(test_trans_node_set)))
UNORDERED_TEST(test_set_transparent_extract,
((test_trans_node_set)))
UNORDERED_TEST(test_set_transparent_bucket,
((test_trans_set)(test_trans_node_set)))
UNORDERED_TEST(test_set_transparent_insert,
((test_trans_set)(test_trans_node_set)))
UNORDERED_TEST(test_set_non_transparent_count,
((test_set1)(test_set2)(test_set3)
(test_node_set1)(test_node_set2)(test_node_set3)))
UNORDERED_TEST(test_set_non_transparent_find,
((test_set1)(test_set2)(test_set3)
(test_node_set1)(test_node_set2)(test_node_set3)))
UNORDERED_TEST(test_set_non_transparent_erase,
((test_set1)(test_set2)(test_set3)
(test_node_set1)(test_node_set2)(test_node_set3)))
UNORDERED_TEST(test_set_non_transparent_equal_range,
((test_set1)(test_set2)(test_set3)
(test_node_set1)(test_node_set2)(test_node_set3)))
UNORDERED_TEST(test_set_non_transparent_extract,
((test_node_set1)(test_node_set2)(test_node_set3)))
UNORDERED_TEST(test_set_non_transparent_bucket,
((test_set1)(test_set2)(test_set3)
(test_node_set1)(test_node_set2)(test_node_set3)))
UNORDERED_TEST(test_set_non_transparent_insert,
((test_set1)(test_set2)(test_set3)
(test_node_set1)(test_node_set2)(test_node_set3)))
// clang-format on
#else
static boost::unordered_set<key, transparent_hasher, transparent_key_equal>*
test_trans_set;
static boost::unordered_multiset<key, transparent_hasher,
transparent_key_equal>* test_trans_multiset;
static boost::unordered_set<key, hasher, key_equal>* test_set1;
static boost::unordered_set<key, transparent_hasher, key_equal>* test_set2;
static boost::unordered_set<key, hasher, transparent_key_equal>* test_set3;
static boost::unordered_multiset<key, hasher, key_equal>* test_multiset1;
static boost::unordered_multiset<key, transparent_hasher, key_equal>*
test_multiset2;
static boost::unordered_multiset<key, hasher, transparent_key_equal>*
test_multiset3;
// clang-format off
UNORDERED_TEST(test_set_transparent_count,
((test_trans_set)(test_trans_multiset)))
UNORDERED_TEST(test_set_transparent_find,
((test_trans_set)(test_trans_multiset)))
UNORDERED_TEST(test_set_transparent_erase,
((test_trans_set)(test_trans_multiset)))
UNORDERED_TEST(test_set_transparent_equal_range,
((test_trans_set)(test_trans_multiset)))
UNORDERED_TEST(test_set_transparent_extract,
((test_trans_set)(test_trans_multiset)))
UNORDERED_TEST(test_set_transparent_bucket,
((test_trans_set)(test_trans_multiset)))
UNORDERED_TEST(test_set_transparent_insert,
((test_trans_set)))
UNORDERED_TEST(test_set_non_transparent_count,
((test_set1)(test_set2)(test_set3)
(test_multiset1)(test_multiset2)(test_multiset3)))
UNORDERED_TEST(test_set_non_transparent_find,
((test_set1)(test_set2)(test_set3)
(test_multiset1)(test_multiset2)(test_multiset3)))
UNORDERED_TEST(test_set_non_transparent_erase,
((test_set1)(test_set2)(test_set3)
(test_multiset1)(test_multiset2)(test_multiset3)))
UNORDERED_TEST(test_set_non_transparent_equal_range,
((test_set1)(test_set2)(test_set3)
(test_multiset1)(test_multiset2)(test_multiset3)))
UNORDERED_TEST(test_set_non_transparent_extract,
((test_set1)(test_set2)(test_set3)
(test_multiset1)(test_multiset2)(test_multiset3)))
UNORDERED_TEST(test_set_non_transparent_bucket,
((test_set1)(test_set2)(test_set3)
(test_multiset1)(test_multiset2)(test_multiset3)))
UNORDERED_TEST(test_set_non_transparent_insert,
((test_set1)(test_set2)(test_set3)))
// clang-format on
#endif
}
RUN_TESTS()