#include <boost/container/detail/config_begin.hpp>
+#include <iostream>
#include <set>
+#include <utility>
+#include <vector>
#include <boost/container/flat_set.hpp>
-#include <boost/container/stable_vector.hpp>
-#include <boost/container/small_vector.hpp>
-#include <boost/container/deque.hpp>
-#include <boost/container/static_vector.hpp>
-#include <boost/container/allocator.hpp>
#include <boost/container/detail/container_or_allocator_rebind.hpp>
#include "print_container.hpp"
using namespace boost::container;
-namespace boost {
-namespace container {
-
-//Explicit instantiation to detect compilation errors
-
-//flat_set
-template class flat_set
- < test::movable_and_copyable_int
- , std::less<test::movable_and_copyable_int>
- , test::simple_allocator<test::movable_and_copyable_int>
- >;
-
-template class flat_set
- < test::movable_and_copyable_int
- , std::less<test::movable_and_copyable_int>
- , small_vector<test::movable_and_copyable_int, 10, allocator<test::movable_and_copyable_int> >
- >;
-
-//flat_multiset
-template class flat_multiset
- < test::movable_and_copyable_int
- , std::less<test::movable_and_copyable_int>
- , stable_vector<test::movable_and_copyable_int, test::simple_allocator<test::movable_and_copyable_int> >
- >;
-
-template class flat_multiset
- < test::movable_and_copyable_int
- , std::less<test::movable_and_copyable_int>
- , deque<test::movable_and_copyable_int, test::simple_allocator< test::movable_and_copyable_int > >
- >;
-
-template class flat_multiset
- < test::movable_and_copyable_int
- , std::less<test::movable_and_copyable_int>
- , static_vector<test::movable_and_copyable_int, 10 >
- >;
-
-//As flat container iterators are typedefs for vector::[const_]iterator,
-//no need to explicit instantiate them
-
-}} //boost::container
-
-
-#if (__cplusplus > 201103L)
-#include <vector>
-
-namespace boost{
-namespace container{
-
-template class flat_set
- < test::movable_and_copyable_int
- , std::less<test::movable_and_copyable_int>
- , std::vector<test::movable_and_copyable_int>
->;
-
-}} //boost::container
-
-#endif
-
//Test recursive structures
class recursive_flat_set
{
return true;
}
+bool constructor_template_auto_deduction_test()
+{
+
+#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
+ using namespace boost::container;
+ const std::size_t NumElements = 100;
+ {
+ std::set<int> int_set;
+ for (std::size_t i = 0; i != NumElements; ++i) {
+ int_set.insert(static_cast<int>(i));
+ }
+ std::multiset<int> int_mset;
+ for (std::size_t i = 0; i != NumElements; ++i) {
+ int_mset.insert(static_cast<int>(i));
+ }
+
+ typedef std::less<int> comp_int_t;
+ typedef std::allocator<int> alloc_int_t;
+
+ //range
+ {
+ auto fset = flat_set(int_set.begin(), int_set.end());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = flat_multiset(int_mset.begin(), int_mset.end());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+comp
+ {
+ auto fset = flat_set(int_set.begin(), int_set.end(), comp_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = flat_multiset(int_mset.begin(), int_mset.end(), comp_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+comp+alloc
+ {
+ auto fset = flat_set(int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = flat_multiset(int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+alloc
+ {
+ auto fset = flat_set(int_set.begin(), int_set.end(), alloc_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = flat_multiset(int_mset.begin(), int_mset.end(), alloc_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+
+ //ordered_unique_range / ordered_range
+
+ //range
+ {
+ auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+comp
+ {
+ auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+comp+alloc
+ {
+ auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+alloc
+ {
+ auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end(), alloc_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end(), alloc_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ }
+#endif
+
+ return true;
+}
+
template< class RandomIt >
void random_shuffle( RandomIt first, RandomIt last )
{
return true;
}
+bool test_heterogeneous_lookups()
+{
+ typedef flat_set<int, test::less_transparent> set_t;
+ typedef flat_multiset<int, test::less_transparent> mset_t;
+
+ set_t set1;
+ mset_t mset1;
+
+ const set_t &cset1 = set1;
+ const mset_t &cmset1 = mset1;
+
+ set1.insert(1);
+ set1.insert(1);
+ set1.insert(2);
+ set1.insert(2);
+ set1.insert(3);
+
+ mset1.insert(1);
+ mset1.insert(1);
+ mset1.insert(2);
+ mset1.insert(2);
+ mset1.insert(3);
+
+ const test::non_copymovable_int find_me(2);
+
+ //find
+ if(*set1.find(find_me) != 2)
+ return false;
+ if(*cset1.find(find_me) != 2)
+ return false;
+ if(*mset1.find(find_me) != 2)
+ return false;
+ if(*cmset1.find(find_me) != 2)
+ return false;
+
+ //count
+ if(set1.count(find_me) != 1)
+ return false;
+ if(cset1.count(find_me) != 1)
+ return false;
+ if(mset1.count(find_me) != 2)
+ return false;
+ if(cmset1.count(find_me) != 2)
+ return false;
+
+ //contains
+ if(!set1.contains(find_me))
+ return false;
+ if(!cset1.contains(find_me))
+ return false;
+ if(!mset1.contains(find_me))
+ return false;
+ if(!cmset1.contains(find_me))
+ return false;
+
+ //lower_bound
+ if(*set1.lower_bound(find_me) != 2)
+ return false;
+ if(*cset1.lower_bound(find_me) != 2)
+ return false;
+ if(*mset1.lower_bound(find_me) != 2)
+ return false;
+ if(*cmset1.lower_bound(find_me) != 2)
+ return false;
+
+ //upper_bound
+ if(*set1.upper_bound(find_me) != 3)
+ return false;
+ if(*cset1.upper_bound(find_me) != 3)
+ return false;
+ if(*mset1.upper_bound(find_me) != 3)
+ return false;
+ if(*cmset1.upper_bound(find_me) != 3)
+ return false;
+
+ //equal_range
+ if(*set1.equal_range(find_me).first != 2)
+ return false;
+ if(*cset1.equal_range(find_me).second != 3)
+ return false;
+ if(*mset1.equal_range(find_me).first != 2)
+ return false;
+ if(*cmset1.equal_range(find_me).second != 3)
+ return false;
+
+ return true;
+}
+
+// An ordered sequence of std:pair is also ordered by std::pair::first.
+struct with_lookup_by_first
+{
+ typedef void is_transparent;
+ inline bool operator()(std::pair<int, int> a, std::pair<int, int> b) const
+ {
+ return a < b;
+ }
+ inline bool operator()(std::pair<int, int> a, int first) const
+ {
+ return a.first < first;
+ }
+ inline bool operator()(int first, std::pair<int, int> b) const
+ {
+ return first < b.first;
+ }
+};
+
+bool test_heterogeneous_lookup_by_partial_key()
+{
+ typedef flat_set<std::pair<int, int>, with_lookup_by_first> set_t;
+
+ set_t set1;
+ set1.insert(std::pair<int, int>(0, 1));
+ set1.insert(std::pair<int, int>(0, 2));
+
+ std::pair<set_t::iterator, set_t::iterator> const first_0_range = set1.equal_range(0);
+ if(2 != (first_0_range.second - first_0_range.first))
+ return false;
+
+ if(2 != set1.count(0))
+ return false;
+ return true;
+}
+
}}}
template<class VoidAllocatorOrContainer>
};
};
-template<class VoidAllocator>
-int test_set_variants()
-{
- typedef typename GetSetContainer<VoidAllocator>::template apply<int>::set_type MySet;
- typedef typename GetSetContainer<VoidAllocator>::template apply<test::movable_int>::set_type MyMoveSet;
- typedef typename GetSetContainer<VoidAllocator>::template apply<test::movable_and_copyable_int>::set_type MyCopyMoveSet;
- typedef typename GetSetContainer<VoidAllocator>::template apply<test::copyable_int>::set_type MyCopySet;
-
- typedef typename GetSetContainer<VoidAllocator>::template apply<int>::multiset_type MyMultiSet;
- typedef typename GetSetContainer<VoidAllocator>::template apply<test::movable_int>::multiset_type MyMoveMultiSet;
- typedef typename GetSetContainer<VoidAllocator>::template apply<test::movable_and_copyable_int>::multiset_type MyCopyMoveMultiSet;
- typedef typename GetSetContainer<VoidAllocator>::template apply<test::copyable_int>::multiset_type MyCopyMultiSet;
-
- typedef std::set<int> MyStdSet;
- typedef std::multiset<int> MyStdMultiSet;
-
- if (0 != test::set_test<
- MySet
- ,MyStdSet
- ,MyMultiSet
- ,MyStdMultiSet>()){
- std::cout << "Error in set_test<MyBoostSet>" << std::endl;
- return 1;
- }
-
- if (0 != test::set_test<
- MyMoveSet
- ,MyStdSet
- ,MyMoveMultiSet
- ,MyStdMultiSet>()){
- std::cout << "Error in set_test<MyBoostSet>" << std::endl;
- return 1;
- }
-
- if (0 != test::set_test<
- MyCopyMoveSet
- ,MyStdSet
- ,MyCopyMoveMultiSet
- ,MyStdMultiSet>()){
- std::cout << "Error in set_test<MyBoostSet>" << std::endl;
- return 1;
- }
-
- if (0 != test::set_test<
- MyCopySet
- ,MyStdSet
- ,MyCopyMultiSet
- ,MyStdMultiSet>()){
- std::cout << "Error in set_test<MyBoostSet>" << std::endl;
- return 1;
- }
-
- return 0;
-}
-
-
template<typename FlatSetType>
bool test_support_for_initialization_list_for()
{
return 1;
}
+ ////////////////////////////////////
+ // Constructor Template Auto Deduction test
+ ////////////////////////////////////
+ if (!constructor_template_auto_deduction_test()) {
+ return 1;
+ }
+
////////////////////////////////////
// Extract/Adopt test
////////////////////////////////////
if (!boost::container::test::instantiate_constructors<flat_set<int>, flat_multiset<int> >())
return 1;
- ////////////////////////////////////
- // Testing allocator implementations
- ////////////////////////////////////
- // std::allocator
- if(test_set_variants< std::allocator<void> >()){
- std::cerr << "test_set_variants< std::allocator<void> > failed" << std::endl;
+ if(!test_heterogeneous_lookups()){
return 1;
}
- // boost::container::allocator
- if(test_set_variants< allocator<void> >()){
- std::cerr << "test_set_variants< allocator<void> > failed" << std::endl;
+
+ if(!test_heterogeneous_lookup_by_partial_key()){
return 1;
}
+ ////////////////////////////////////
+ // Testing allocator implementations
+ ////////////////////////////////////
+ {
+ typedef std::set<int> MyStdSet;
+ typedef std::multiset<int> MyStdMultiSet;
+
+ if (0 != test::set_test
+ < GetSetContainer<std::allocator<void> >::apply<int>::set_type
+ , MyStdSet
+ , GetSetContainer<std::allocator<void> >::apply<int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<std::allocator<void> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::set_test
+ < GetSetContainer<new_allocator<void> >::apply<int>::set_type
+ , MyStdSet
+ , GetSetContainer<new_allocator<void> >::apply<int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<new_allocator<void> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::set_test
+ < GetSetContainer<new_allocator<void> >::apply<test::movable_int>::set_type
+ , MyStdSet
+ , GetSetContainer<new_allocator<void> >::apply<test::movable_int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<new_allocator<void> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::set_test
+ < GetSetContainer<new_allocator<void> >::apply<test::copyable_int>::set_type
+ , MyStdSet
+ , GetSetContainer<new_allocator<void> >::apply<test::copyable_int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<new_allocator<void> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::set_test
+ < GetSetContainer<new_allocator<void> >::apply<test::movable_and_copyable_int>::set_type
+ , MyStdSet
+ , GetSetContainer<new_allocator<void> >::apply<test::movable_and_copyable_int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<new_allocator<void> >" << std::endl;
+ return 1;
+ }
+ }
+
////////////////////////////////////
// Emplace testing
////////////////////////////////////
}
}
+ ////////////////////////////////////
+ // has_trivial_destructor_after_move testing
+ ////////////////////////////////////
+ {
+ typedef boost::container::dtl::identity<int> key_of_value_t;
+ // flat_set, default
+ {
+ typedef boost::container::flat_set<int> cont;
+ typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, void> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_set, default) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // flat_set, vector
+ {
+ typedef boost::container::vector<int> alloc_or_cont_t;
+ typedef boost::container::flat_set<int, std::less<int>, alloc_or_cont_t> cont;
+ typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_set, vector) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // flat_set, std::vector
+ {
+ typedef std::vector<int> alloc_or_cont_t;
+ typedef boost::container::flat_set<int, std::less<int>, alloc_or_cont_t> cont;
+ typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_set, std::vector) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // flat_multiset, default
+ {
+ typedef boost::container::flat_multiset<int> cont;
+ typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, void> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_multiset, default) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // flat_multiset, vector
+ {
+ typedef boost::container::vector<int> alloc_or_cont_t;
+ typedef boost::container::flat_multiset<int, std::less<int>, alloc_or_cont_t> cont;
+ typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_multiset, vector) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // flat_multiset, std::vector
+ {
+ typedef std::vector<int> alloc_or_cont_t;
+ typedef boost::container::flat_multiset<int, std::less<int>, alloc_or_cont_t> cont;
+ typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_multiset, std::vector) test failed" << std::endl;
+ return 1;
+ }
+ }
+ }
+
return 0;
}