diff --git a/example/doc_map.cpp b/example/doc_map.cpp new file mode 100644 index 0000000..766dd89 --- /dev/null +++ b/example/doc_map.cpp @@ -0,0 +1,84 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2015-2015 +// +// 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 http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +//[doc_map_code +#include +#include +#include +#include +#include +#include + +using namespace boost::intrusive; + +class MyClass : public set_base_hook<> + , public unordered_set_base_hook<> +{ + public: + int first; + explicit MyClass(int i) : first(i){} +}; + +//key_of_value function object, must: +//- be default constructible (and lightweight) +//- define the key type using "type" +//- define an operator() taking "const value_type&" and +// returning "const type &" +struct first_int_is_key +{ + typedef int type; + + const type & operator()(const MyClass& v) const + { return v.first; } +}; + +//Define omap like ordered and unordered classes +typedef set< MyClass, key_of_value > OrderedMap; +typedef unordered_set< MyClass, key_of_value > UnorderedMap; + +int main() +{ + BOOST_STATIC_ASSERT((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); + + //Create several MyClass objects, each one with a different value + //and insert them into the omap + std::vector values; + for(int i = 0; i < 100; ++i) values.push_back(MyClass(i)); + + //Create ordered/unordered maps and insert values + OrderedMap omap(values.begin(), values.end()); + UnorderedMap::bucket_type buckets[100]; + UnorderedMap umap(values.begin(), values.end(), UnorderedMap::bucket_traits(buckets, 100)); + + //Test each element using the key_type (int) + for(int i = 0; i != 100; ++i){ + assert(omap.find(i) != omap.end()); + assert(umap.find(i) != umap.end()); + assert(omap.lower_bound(i) != omap.end()); + assert(++omap.lower_bound(i) == omap.upper_bound(i)); + assert(omap.equal_range(i).first != omap.equal_range(i).second); + assert(umap.equal_range(i).first != umap.equal_range(i).second); + } + + //Count and erase by key + for(int i = 0; i != 100; ++i){ + assert(1 == omap.count(i)); + assert(1 == umap.count(i)); + assert(1 == omap.erase(i)); + assert(1 == umap.erase(i)); + } + assert(omap.empty()); + assert(umap.empty()); + + return 0; +} +//] diff --git a/proj/vc7ide/bs_multiset/bsl_multiset.vcproj b/proj/vc7ide/bs_multiset/bsl_multiset.vcproj new file mode 100644 index 0000000..45ef620 --- /dev/null +++ b/proj/vc7ide/bs_multiset/bsl_multiset.vcproj @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/bs_set/bs_set.vcproj b/proj/vc7ide/bs_set/bs_set.vcproj new file mode 100644 index 0000000..e707da2 --- /dev/null +++ b/proj/vc7ide/bs_set/bs_set.vcproj @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/avl_test_common.hpp b/test/avl_test_common.hpp new file mode 100644 index 0000000..eed1659 --- /dev/null +++ b/test/avl_test_common.hpp @@ -0,0 +1,45 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2015-2015. +// +// 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 http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_TEST_AVL_TEST_COMMON_HPP +#define BOOST_INTRUSIVE_TEST_AVL_TEST_COMMON_HPP + +#include +#include +#include "bs_test_common.hpp" + +namespace boost { +namespace intrusive { + +template +struct avl_hooks +{ + typedef avl_set_base_hook > base_hook_type; + typedef avl_set_base_hook + + , void_pointer + , tag + , optimize_size > auto_base_hook_type; + typedef avl_set_member_hook + + , optimize_size > member_hook_type; + typedef avl_set_member_hook + < link_mode + , void_pointer > auto_member_hook_type; + typedef nonhook_node_member< avltree_node_traits, + avltree_algorithms + > nonhook_node_member_type; +}; + +} //namespace intrusive { +} //namespace boost { + +#endif //BOOST_INTRUSIVE_TEST_AVL_TEST_COMMON_HPP diff --git a/test/bs_multiset_test.cpp b/test/bs_multiset_test.cpp new file mode 100644 index 0000000..8133be1 --- /dev/null +++ b/test/bs_multiset_test.cpp @@ -0,0 +1,128 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2015. +// +// 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 http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#include +#include "itestvalue.hpp" +#include "bptr_value.hpp" +#include "smart_ptr.hpp" +#include "bs_test_common.hpp" +#include "generic_multiset_test.hpp" + +using namespace boost::intrusive; + +template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map > +struct rebinder +{ + typedef tree_rebinder_common common_t; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef bs_multiset + < typename common_t::value_type + , value_traits + , constant_time_size + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester::value)); + }; +}; + +template +class test_main_template +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks > testval_traits_t; + //base + typedef typename detail::if_c + < ConstantTimeSize + , typename testval_traits_t::base_value_traits + , typename testval_traits_t::auto_base_value_traits + >::type base_hook_t; + test::test_generic_multiset + < base_hook_t + , rebinder + >::test_all(); + //member + typedef typename detail::if_c + < ConstantTimeSize + , typename testval_traits_t::member_value_traits + , typename testval_traits_t::auto_member_value_traits + >::type member_hook_t; + test::test_generic_multiset + < member_hook_t + , rebinder + >::test_all(); + //nonmember + test::test_generic_multiset + < typename testval_traits_t::nonhook_value_traits + , rebinder + >::test_all(); + } +}; + +template < bool ConstantTimeSize, bool Map > +struct test_main_template_bptr +{ + static void execute() + { + typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits; + typedef bounded_allocator< BPtr_Value > allocator_type; + + bounded_allocator_scope bounded_scope; (void)bounded_scope; + test::test_generic_multiset + < value_traits + , rebinder< value_traits, ConstantTimeSize, true, Map> + >::test_all(); + } +}; + +int main() +{ + //Combinations: VoidPointer x ConstantTimeSize x DefaultHolder x Map + //Minimize them selecting different combinations for raw and smart pointers + //Start with ('false', 'false', 'false') in sets and 'false', 'false', 'true' in multisets + + //void pointer + //test_main_template::execute(); + test_main_template::execute(); + //test_main_template::execute(); + test_main_template::execute(); + //test_main_template::execute(); + test_main_template::execute(); + //test_main_template::execute(); + test_main_template::execute(); + + //smart_ptr + test_main_template, false, false, false>::execute(); + //test_main_template, false, false, true>::execute(); + test_main_template, false, true, false>::execute(); + //test_main_template, false, true, true>::execute(); + test_main_template, true, false, false>::execute(); + //test_main_template, true, false, true>::execute(); + test_main_template, true, true, false>::execute(); + //test_main_template, true, true, true>::execute(); + + //bounded_ptr (bool ConstantTimeSize, bool Map) + //test_main_template_bptr< false, false >::execute(); + test_main_template_bptr< false, true >::execute(); + test_main_template_bptr< true, false >::execute(); + //test_main_template_bptr< true, true >::execute(); + + return boost::report_errors(); +} diff --git a/test/bs_set_test.cpp b/test/bs_set_test.cpp new file mode 100644 index 0000000..2574312 --- /dev/null +++ b/test/bs_set_test.cpp @@ -0,0 +1,128 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2015. +// +// 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 http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#include +#include "itestvalue.hpp" +#include "bptr_value.hpp" +#include "smart_ptr.hpp" +#include "generic_set_test.hpp" +#include "bs_test_common.hpp" + +using namespace boost::intrusive; + +template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map > +struct rebinder +{ + typedef tree_rebinder_common common_t; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef bs_set + < typename common_t::value_type + , value_traits + , constant_time_size + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester::value)); + }; +}; + +template +class test_main_template +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks > testval_traits_t; + //base + typedef typename detail::if_c + < ConstantTimeSize + , typename testval_traits_t::base_value_traits + , typename testval_traits_t::auto_base_value_traits + >::type base_hook_t; + test::test_generic_set + < base_hook_t + , rebinder + >::test_all(); + //member + typedef typename detail::if_c + < ConstantTimeSize + , typename testval_traits_t::member_value_traits + , typename testval_traits_t::auto_member_value_traits + >::type member_hook_t; + test::test_generic_set + < member_hook_t + , rebinder + >::test_all(); + //nonmember + test::test_generic_set + < typename testval_traits_t::nonhook_value_traits + , rebinder + >::test_all(); + } +}; + +template < bool ConstantTimeSize, bool Map > +struct test_main_template_bptr +{ + static void execute() + { + typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits; + typedef bounded_allocator< BPtr_Value > allocator_type; + + bounded_allocator_scope bounded_scope; (void)bounded_scope; + test::test_generic_set + < value_traits + , rebinder< value_traits, ConstantTimeSize, true, Map> + >::test_all(); + } +}; + +int main() +{ + //Combinations: VoidPointer x ConstantTimeSize x DefaultHolder x Map + //Minimize them selecting different combinations for raw and smart pointers + //Start with ('false', 'false', 'false') in sets and 'false', 'false', 'true' in multisets + + //void pointer + test_main_template::execute(); + //test_main_template::execute(); + test_main_template::execute(); + //test_main_template::execute(); + test_main_template::execute(); + //test_main_template::execute(); + test_main_template::execute(); + //test_main_template::execute(); + + //smart_ptr + //test_main_template, false, false, false>::execute(); + test_main_template, false, false, true>::execute(); + //test_main_template, false, true, false>::execute(); + test_main_template, false, true, true>::execute(); + //test_main_template, true, false, false>::execute(); + test_main_template, true, false, true>::execute(); + //test_main_template, true, true, false>::execute(); + test_main_template, true, true, true>::execute(); + + //bounded_ptr (bool ConstantTimeSize, bool Map) + //test_main_template_bptr< false, false >::execute(); + test_main_template_bptr< false, true >::execute(); + test_main_template_bptr< true, false >::execute(); + //test_main_template_bptr< true, true >::execute(); + + return boost::report_errors(); +} diff --git a/test/bs_test_common.hpp b/test/bs_test_common.hpp new file mode 100644 index 0000000..4574c86 --- /dev/null +++ b/test/bs_test_common.hpp @@ -0,0 +1,63 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2015-2015. +// +// 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 http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_TEST_BS_TEST_COMMON_HPP +#define BOOST_INTRUSIVE_TEST_BS_TEST_COMMON_HPP + +#include +#include +#include "bptr_value.hpp" +#include "test_common.hpp" + +namespace boost { +namespace intrusive { + +template +struct bs_hooks +{ + typedef bs_set_base_hook > base_hook_type; + typedef bs_set_base_hook + + , void_pointer + , tag > auto_base_hook_type; + typedef bs_set_member_hook + > member_hook_type; + typedef bs_set_member_hook + < link_mode + , void_pointer > auto_member_hook_type; + typedef nonhook_node_member< tree_node_traits, + bstree_algorithms + > nonhook_node_member_type; +}; + +template < class ValueTraits, bool DefaultHolder, bool Map > +struct tree_rebinder_common +{ + typedef typename ValueTraits::value_type value_type; + typedef typename detail::if_c + < DefaultHolder + , typename detail::if_c + < detail::is_same::value + , header_holder_type< bounded_pointer_holder< BPtr_Value > > + , void + >::type + , header_holder_type< heap_node_holder< typename ValueTraits::node_ptr > > + >::type holder_opt; + typedef typename detail::if_c + < Map, key_of_value >, void + >::type key_of_value_opt; +}; + + +} //namespace intrusive { +} //namespace boost { + +#endif //BOOST_INTRUSIVE_TEST_BS_TEST_COMMON_HPP diff --git a/test/int_holder.hpp b/test/int_holder.hpp new file mode 100644 index 0000000..412217d --- /dev/null +++ b/test/int_holder.hpp @@ -0,0 +1,106 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2015-2015. +// +// 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 http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_DETAIL_INT_HOLDER_HPP +#define BOOST_INTRUSIVE_DETAIL_INT_HOLDER_HPP + +namespace boost{ +namespace intrusive{ + +struct int_holder +{ + explicit int_holder(int value = 0) + : int_(value) + {} + + int_holder &operator=(int value) + { int_ = value; return *this; } + + int int_value() const + { return int_; } + + friend bool operator==(const int_holder &l, const int_holder &r) + { return l.int_ == r.int_; } + + friend bool operator!=(const int_holder &l, const int_holder &r) + { return l.int_ != r.int_; } + + friend bool operator<(const int_holder &l, const int_holder &r) + { return l.int_ < r.int_; } + + friend bool operator>(const int_holder &l, const int_holder &r) + { return l.int_ > r.int_; } + + friend bool operator<=(const int_holder &l, const int_holder &r) + { return l.int_ <= r.int_; } + + friend bool operator>=(const int_holder &l, const int_holder &r) + { return l.int_ >= r.int_; } + +/// + friend bool operator==(int l, const int_holder &r) + { return l == r.int_; } + + friend bool operator!=(int l, const int_holder &r) + { return l != r.int_; } + + friend bool operator<(int l, const int_holder &r) + { return l < r.int_; } + + friend bool operator>(int l, const int_holder &r) + { return l > r.int_; } + + friend bool operator<=(int l, const int_holder &r) + { return l <= r.int_; } + + friend bool operator>=(int l, const int_holder &r) + { return l >= r.int_; } + + bool operator< (int i) const + { return int_ < i; } + + bool operator> (int i) const + { return int_ > i; } + + bool operator<= (int i) const + { return int_ <= i; } + + bool operator>= (int i) const + { return int_ >= i; } + + bool operator== (int i) const + { return int_ == i; } + + bool operator!= (int i) const + { return int_ != i; } + + friend std::size_t hash_value(const int_holder &t) + { + boost::hash hasher; + return hasher((&t)->int_value()); + } + + int int_; +}; + +template +struct int_holder_key_of_value +{ + typedef int_holder type; + + const type &operator()(const ValueType &tv) + { return tv.get_int_holder(); } +}; + +} //namespace boost{ +} //namespace intrusive{ + +#endif //BOOST_INTRUSIVE_DETAIL_INT_HOLDER_HPP diff --git a/test/rb_test_common.hpp b/test/rb_test_common.hpp new file mode 100644 index 0000000..f9aa512 --- /dev/null +++ b/test/rb_test_common.hpp @@ -0,0 +1,45 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2015-2015. +// +// 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 http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_TEST_RB_TEST_COMMON_HPP +#define BOOST_INTRUSIVE_TEST_RB_TEST_COMMON_HPP + +#include +#include +#include "bs_test_common.hpp" + +namespace boost { +namespace intrusive { + +template +struct rb_hooks +{ + typedef set_base_hook > base_hook_type; + typedef set_base_hook + + , void_pointer + , tag + , optimize_size > auto_base_hook_type; + typedef set_member_hook + + , optimize_size > member_hook_type; + typedef set_member_hook + < link_mode + , void_pointer > auto_member_hook_type; + typedef nonhook_node_member< rbtree_node_traits, + rbtree_algorithms + > nonhook_node_member_type; +}; + +} //namespace intrusive { +} //namespace boost { + +#endif //BOOST_INTRUSIVE_TEST_RB_TEST_COMMON_HPP diff --git a/test/test_common.hpp b/test/test_common.hpp new file mode 100644 index 0000000..8c7ae48 --- /dev/null +++ b/test/test_common.hpp @@ -0,0 +1,57 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2015-2015. +// +// 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 http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_TEST_TEST_COMMON_HPP +#define BOOST_INTRUSIVE_TEST_TEST_COMMON_HPP + +#include +#include +#include "bptr_value.hpp" + +namespace boost { +namespace intrusive { + +template +struct key_type_tester +{ + struct empty_default{}; + typedef typename pack_options< empty_default, KeyOfValueOption >::type::key_of_value key_of_value_t; + + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same< KeyOfValueOption + , key_of_value > + >::value )); + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same< key_of_value_t + , int_holder_key_of_value + >::value )); + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same< typename Map::key_type + , typename key_of_value_t::type >::value )); + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same< typename Map::key_of_value + , key_of_value_t >::value )); + static const bool value = true; +}; + +template +struct key_type_tester +{ + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same< typename Map::key_type + , typename Map::value_type + >::value )); + + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same< typename Map::key_of_value + , boost::intrusive::detail::identity< typename Map::value_type> + >::value )); + static const bool value = true; +}; + +} //namespace intrusive { +} //namespace boost { + +#endif //BOOST_INTRUSIVE_TEST_TEST_COMMON_HPP diff --git a/test/unordered_test.hpp b/test/unordered_test.hpp new file mode 100644 index 0000000..38d6ddc --- /dev/null +++ b/test/unordered_test.hpp @@ -0,0 +1,853 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2015-2015. +// +// 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 http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#include +#include +#include "common_functors.hpp" +#include +#include //std::sort +#include +#include + +#include "test_macros.hpp" +#include "test_container.hpp" +#include "unordered_test_common.hpp" + +namespace boost{ +namespace intrusive{ +namespace test{ + +static const std::size_t BucketSize = 8; + +template +struct test_unordered +{ + typedef typename ValueTraits::value_type value_type; + typedef typename ValueTraits::pointer pointer; + typedef typename ValueTraits::const_pointer const_pointer; + typedef typename ValueContainer< value_type >::type value_cont_type; + typedef typename pointer_traits::reference reference; + typedef typename pointer_traits + ::reference const_reference; + + static void test_all(value_cont_type& values); + private: + static void test_sort(value_cont_type& values); + static void test_insert(value_cont_type& values, detail::true_); + static void test_insert(value_cont_type& values, detail::false_); + static void test_swap(value_cont_type& values); + static void test_rehash(value_cont_type& values, detail::true_); + static void test_rehash(value_cont_type& values, detail::false_); + static void test_find(value_cont_type& values); + static void test_impl(); + static void test_clone(value_cont_type& values); +}; + +template +void test_unordered:: + test_all (value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + typedef typename unordered_type::bucket_traits bucket_traits; + { + typename unordered_type::bucket_type buckets [BucketSize]; + unordered_type testset + (bucket_traits(pointer_traits:: + pointer_to(buckets[0]), BucketSize)); + testset.insert(values.begin(), values.end()); + test::test_container(testset); + testset.clear(); + testset.insert(values.begin(), values.end()); + test::test_common_unordered_and_associative_container(testset, values); + testset.clear(); + testset.insert(values.begin(), values.end()); + test::test_unordered_associative_container(testset, values); + testset.clear(); + testset.insert(values.begin(), values.end()); + typedef detail::bool_::value> select_t; + test::test_maybe_unique_container(testset, values, select_t()); + } + { + value_cont_type values(BucketSize); + for (int i = 0; i < (int)BucketSize; ++i) + (&values[i])->value_ = i; + typename unordered_type::bucket_type buckets [BucketSize]; + unordered_type testset(bucket_traits( + pointer_traits:: + pointer_to(buckets[0]), BucketSize)); + testset.insert(values.begin(), values.end()); + test::test_iterator_forward(testset); + } + test_sort(values); + test_insert(values, detail::bool_::value>()); + test_swap(values); + test_rehash(values, detail::bool_()); + test_find(values); + test_impl(); + test_clone(values); +} + +//test case due to an error in tree implementation: +template +void test_unordered + ::test_impl() +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + typedef typename unordered_type::bucket_traits bucket_traits; + + value_cont_type values (5); + for (int i = 0; i < 5; ++i) + values[i].value_ = i; + + typename unordered_type::bucket_type buckets [BucketSize]; + unordered_type testset(bucket_traits( + pointer_traits:: + pointer_to(buckets[0]), BucketSize)); + + for (int i = 0; i < 5; ++i) + testset.insert (values[i]); + + testset.erase (testset.iterator_to (values[0])); + testset.erase (testset.iterator_to (values[1])); + testset.insert (values[1]); + + testset.erase (testset.iterator_to (values[2])); + testset.erase (testset.iterator_to (values[3])); +} + +//test: constructor, iterator, clear, reverse_iterator, front, back, size: +template +void test_unordered + ::test_sort(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + typedef typename unordered_type::bucket_traits bucket_traits; + + typename unordered_type::bucket_type buckets [BucketSize]; + unordered_type testset1 + (values.begin(), values.end(), bucket_traits + (pointer_traits:: + pointer_to(buckets[0]), BucketSize)); + + if(unordered_type::incremental){ + { int init_values [] = { 4, 5, 1, 2, 2, 3 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + } + else{ + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + } + testset1.clear(); + BOOST_TEST (testset1.empty()); +} + +//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to: +template +void test_unordered + ::test_insert(value_cont_type& values, detail::false_) //not multikey +{ + + typedef typename ContainerDefiner::template container + <>::type unordered_set_type; + typedef typename unordered_set_type::bucket_traits bucket_traits; + + typename unordered_set_type::bucket_type buckets [BucketSize]; + unordered_set_type testset(bucket_traits( + pointer_traits:: + pointer_to(buckets[0]), BucketSize)); + testset.insert(&values[0] + 2, &values[0] + 5); + + const unordered_set_type& const_testset = testset; + if(unordered_set_type::incremental) + { + { int init_values [] = { 4, 5, 1 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); } + typename unordered_set_type::iterator i = testset.begin(); + BOOST_TEST (i->value_ == 4); + + i = testset.insert(values[0]).first; + BOOST_TEST (&*i == &values[0]); + + i = testset.iterator_to (values[2]); + BOOST_TEST (&*i == &values[2]); + + testset.erase (i); + + { int init_values [] = { 5, 1, 3 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); } + } + else{ + { int init_values [] = { 1, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); } + typename unordered_set_type::iterator i = testset.begin(); + BOOST_TEST (i->value_ == 1); + + i = testset.insert(values[0]).first; + BOOST_TEST (&*i == &values[0]); + + i = testset.iterator_to (values[2]); + BOOST_TEST (&*i == &values[2]); + + testset.erase (i); + + { int init_values [] = { 1, 3, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); } + } +} + +template +void test_unordered + ::test_insert(value_cont_type& values, detail::true_) //is multikey +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + + typedef typename unordered_type::bucket_traits bucket_traits; + typedef typename unordered_type::iterator iterator; + typedef typename unordered_type::key_type key_type; + { + typename unordered_type::bucket_type buckets [BucketSize]; + unordered_type testset(bucket_traits( + pointer_traits:: + pointer_to(buckets[0]), BucketSize)); + + testset.insert(&values[0] + 2, &values[0] + 5); + + const unordered_type& const_testset = testset; + + if(unordered_type::incremental){ + { + { int init_values [] = { 4, 5, 1 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); } + + typename unordered_type::iterator i = testset.begin(); + BOOST_TEST (i->value_ == 4); + + i = testset.insert (values[0]); + BOOST_TEST (&*i == &values[0]); + + i = testset.iterator_to (values[2]); + BOOST_TEST (&*i == &values[2]); + testset.erase(i); + + { int init_values [] = { 5, 1, 3 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); } + testset.clear(); + testset.insert(&values[0], &values[0] + values.size()); + + { int init_values [] = { 4, 5, 1, 2, 2, 3 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); } + + BOOST_TEST (testset.erase(key_type(1)) == 1); + BOOST_TEST (testset.erase(key_type(2)) == 2); + BOOST_TEST (testset.erase(key_type(3)) == 1); + BOOST_TEST (testset.erase(key_type(4)) == 1); + BOOST_TEST (testset.erase(key_type(5)) == 1); + BOOST_TEST (testset.empty() == true); + + //Now with a single bucket + typename unordered_type::bucket_type single_bucket[1]; + unordered_type testset2(bucket_traits( + pointer_traits:: + pointer_to(single_bucket[0]), 1)); + testset2.insert(&values[0], &values[0] + values.size()); + BOOST_TEST (testset2.erase(key_type(5)) == 1); + BOOST_TEST (testset2.erase(key_type(2)) == 2); + BOOST_TEST (testset2.erase(key_type(1)) == 1); + BOOST_TEST (testset2.erase(key_type(4)) == 1); + BOOST_TEST (testset2.erase(key_type(3)) == 1); + BOOST_TEST (testset2.empty() == true); + } + } + else{ + { + { int init_values [] = { 1, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); } + + typename unordered_type::iterator i = testset.begin(); + BOOST_TEST (i->value_ == 1); + + i = testset.insert (values[0]); + BOOST_TEST (&*i == &values[0]); + + i = testset.iterator_to (values[2]); + BOOST_TEST (&*i == &values[2]); + testset.erase(i); + + { int init_values [] = { 1, 3, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); } + testset.clear(); + testset.insert(&values[0], &values[0] + values.size()); + + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); } + + BOOST_TEST (testset.erase(key_type(1)) == 1); + BOOST_TEST (testset.erase(key_type(2)) == 2); + BOOST_TEST (testset.erase(key_type(3)) == 1); + BOOST_TEST (testset.erase(key_type(4)) == 1); + BOOST_TEST (testset.erase(key_type(5)) == 1); + BOOST_TEST (testset.empty() == true); + + //Now with a single bucket + typename unordered_type::bucket_type single_bucket[1]; + unordered_type testset2(bucket_traits( + pointer_traits:: + pointer_to(single_bucket[0]), 1)); + testset2.insert(&values[0], &values[0] + values.size()); + BOOST_TEST (testset2.erase(key_type(5)) == 1); + BOOST_TEST (testset2.erase(key_type(2)) == 2); + BOOST_TEST (testset2.erase(key_type(1)) == 1); + BOOST_TEST (testset2.erase(key_type(4)) == 1); + BOOST_TEST (testset2.erase(key_type(3)) == 1); + BOOST_TEST (testset2.empty() == true); + } + } + { + //Now erase just one per loop + const int random_init[] = { 3, 2, 4, 1, 5, 2, 2 }; + const unsigned int random_size = sizeof(random_init)/sizeof(random_init[0]); + typename unordered_type::bucket_type single_bucket[1]; + for(unsigned int i = 0, max = random_size; i != max; ++i){ + value_cont_type data (random_size); + for (unsigned int j = 0; j < random_size; ++j) + data[j].value_ = random_init[j]; + unordered_type testset_new(bucket_traits( + pointer_traits:: + pointer_to(single_bucket[0]), 1)); + testset_new.insert(&data[0], &data[0]+max); + testset_new.erase(testset_new.iterator_to(data[i])); + BOOST_TEST (testset_new.size() == (max -1)); + } + } + } + { + typename unordered_type::bucket_type buckets [BucketSize]; + const unsigned int NumBucketSize = BucketSize; + const unsigned int LoadFactor = 3; + const unsigned int NumIterations = NumBucketSize*LoadFactor; + value_cont_type random_init(NumIterations);//Preserve memory + value_cont_type set_tester; + set_tester.reserve(NumIterations); + + //Initialize values + for (unsigned int i = 0; i < NumIterations; ++i){ + random_init[i].value_ = i*2;//(i/LoadFactor)*LoadFactor; + } + + for(unsigned int initial_pos = 0; initial_pos != (NumIterations+1); ++initial_pos){ + for(unsigned int final_pos = initial_pos; final_pos != (NumIterations+1); ++final_pos){ + + //Create intrusive container inserting values + unordered_type testset + ( &random_init[0] + , &random_init[0] + random_init.size() + , bucket_traits(pointer_traits:: + pointer_to(buckets[0]), NumBucketSize)); + + BOOST_TEST (testset.size() == random_init.size()); + + //Obtain the iterator range to erase + iterator it_beg_pos = testset.begin(); + for(unsigned int it_beg_pos_num = 0; it_beg_pos_num != initial_pos; ++it_beg_pos_num){ + ++it_beg_pos; + } + iterator it_end_pos(it_beg_pos); + for(unsigned int it_end_pos_num = 0; it_end_pos_num != (final_pos - initial_pos); ++it_end_pos_num){ + ++it_end_pos; + } + + //Erase the same values in both the intrusive and original vector + std::size_t erased_cnt = boost::intrusive::iterator_distance(it_beg_pos, it_end_pos); + + //Erase values from the intrusive container + testset.erase(it_beg_pos, it_end_pos); + + BOOST_TEST (testset.size() == (random_init.size()-(final_pos - initial_pos))); + + //Now test... + BOOST_TEST ((random_init.size() - erased_cnt) == testset.size()); + + //Create an ordered copy of the intrusive container + set_tester.insert(set_tester.end(), testset.begin(), testset.end()); + std::sort(set_tester.begin(), set_tester.end()); + { + typename value_cont_type::iterator it = set_tester.begin(), itend = set_tester.end(); + typename value_cont_type::iterator random_init_it(random_init.begin()); + for( ; it != itend; ++it){ + while(!random_init_it->is_linked()) + ++random_init_it; + BOOST_TEST(*it == *random_init_it); + ++random_init_it; + } + } + set_tester.clear(); + } + } + } +} + +//test: insert (seq-version), swap, erase (seq-version), size: +template +void test_unordered:: + test_swap(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + + typedef typename unordered_type::bucket_traits bucket_traits; + typename unordered_type::bucket_type buckets [BucketSize]; + + typename unordered_type::bucket_type buckets2 [BucketSize]; + unordered_type testset1(&values[0], &values[0] + 2, + bucket_traits(pointer_traits:: + pointer_to(buckets[0]), BucketSize)); + unordered_type testset2(bucket_traits( + pointer_traits:: + pointer_to(buckets2[0]), BucketSize)); + + testset2.insert (&values[0] + 2, &values[0] + 6); + testset1.swap (testset2); + + if(unordered_type::incremental){ + { int init_values [] = { 4, 5, 1, 2 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + + { int init_values [] = { 2, 3 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset2 ); } + testset1.erase (testset1.iterator_to(values[4]), testset1.end()); + BOOST_TEST (testset1.size() == 1); + // BOOST_TEST (&testset1.front() == &values[3]); + BOOST_TEST (&*testset1.begin() == &values[2]); + } + else{ + { int init_values [] = { 1, 2, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + + { int init_values [] = { 2, 3 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset2 ); } + testset1.erase (testset1.iterator_to(values[5]), testset1.end()); + BOOST_TEST (testset1.size() == 1); + // BOOST_TEST (&testset1.front() == &values[3]); + BOOST_TEST (&*testset1.begin() == &values[3]); + } +} + + + +//test: rehash: + +template +void test_unordered + ::test_rehash(value_cont_type& values, detail::true_) +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + + typedef typename unordered_type::bucket_traits bucket_traits; + //Build a uset + typename unordered_type::bucket_type buckets1 [BucketSize]; + typename unordered_type::bucket_type buckets2 [BucketSize*2]; + unordered_type testset1(&values[0], &values[0] + values.size(), + bucket_traits(pointer_traits:: + pointer_to(buckets1[0]), BucketSize)); + //Test current state + BOOST_TEST(testset1.split_count() == BucketSize/2); + { int init_values [] = { 4, 5, 1, 2, 2, 3 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + //Incremental rehash step + BOOST_TEST (testset1.incremental_rehash() == true); + BOOST_TEST(testset1.split_count() == (BucketSize/2+1)); + { int init_values [] = { 5, 1, 2, 2, 3, 4 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + //Rest of incremental rehashes should lead to the same sequence + for(std::size_t split_bucket = testset1.split_count(); split_bucket != BucketSize; ++split_bucket){ + BOOST_TEST (testset1.incremental_rehash() == true); + BOOST_TEST(testset1.split_count() == (split_bucket+1)); + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + } + //This incremental rehash should fail because we've reached the end of the bucket array + BOOST_TEST (testset1.incremental_rehash() == false); + BOOST_TEST(testset1.split_count() == BucketSize); + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + + // + //Try incremental hashing specifying a new bucket traits pointing to the same array + // + //This incremental rehash should fail because the new size is not twice the original + BOOST_TEST(testset1.incremental_rehash(bucket_traits( + pointer_traits:: + pointer_to(buckets1[0]), BucketSize)) == false); + BOOST_TEST(testset1.split_count() == BucketSize); + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + + // + //Try incremental hashing specifying a new bucket traits pointing to the same array + // + //This incremental rehash should fail because the new size is not twice the original + BOOST_TEST(testset1.incremental_rehash(bucket_traits( + pointer_traits:: + pointer_to(buckets2[0]), BucketSize)) == false); + BOOST_TEST(testset1.split_count() == BucketSize); + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + + //This incremental rehash should success because the new size is twice the original + //and split_count is the same as the old bucket count + BOOST_TEST(testset1.incremental_rehash(bucket_traits( + pointer_traits:: + pointer_to(buckets2[0]), BucketSize*2)) == true); + BOOST_TEST(testset1.split_count() == BucketSize); + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + + //This incremental rehash should also success because the new size is half the original + //and split_count is the same as the new bucket count + BOOST_TEST(testset1.incremental_rehash(bucket_traits( + pointer_traits:: + pointer_to(buckets1[0]), BucketSize)) == true); + BOOST_TEST(testset1.split_count() == BucketSize); + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + + //Full shrink rehash + testset1.rehash(bucket_traits( + pointer_traits:: + pointer_to(buckets1[0]), 4)); + BOOST_TEST (testset1.incremental_rehash() == false); + { int init_values [] = { 4, 5, 1, 2, 2, 3 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + //Full shrink rehash again + testset1.rehash(bucket_traits( + pointer_traits:: + pointer_to(buckets1[0]), 2)); + BOOST_TEST (testset1.incremental_rehash() == false); + { int init_values [] = { 2, 2, 4, 3, 5, 1 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + //Full growing rehash + testset1.rehash(bucket_traits( + pointer_traits:: + pointer_to(buckets1[0]), BucketSize)); + BOOST_TEST (testset1.incremental_rehash() == false); + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + //Incremental rehash shrinking + //First incremental rehashes should lead to the same sequence + for(std::size_t split_bucket = testset1.split_count(); split_bucket > 6; --split_bucket){ + BOOST_TEST (testset1.incremental_rehash(false) == true); + BOOST_TEST(testset1.split_count() == (split_bucket-1)); + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + } + //Incremental rehash step + BOOST_TEST (testset1.incremental_rehash(false) == true); + BOOST_TEST(testset1.split_count() == (BucketSize/2+1)); + { int init_values [] = { 5, 1, 2, 2, 3, 4 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + //Incremental rehash step 2 + BOOST_TEST (testset1.incremental_rehash(false) == true); + BOOST_TEST(testset1.split_count() == (BucketSize/2)); + { int init_values [] = { 4, 5, 1, 2, 2, 3 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + //This incremental rehash should fail because we've reached the half of the bucket array + BOOST_TEST(testset1.incremental_rehash(false) == false); + BOOST_TEST(testset1.split_count() == BucketSize/2); + { int init_values [] = { 4, 5, 1, 2, 2, 3 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } +} +template +void test_unordered + ::test_rehash(value_cont_type& values, detail::false_) +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + + typedef typename unordered_type::bucket_traits bucket_traits; + + typename unordered_type::bucket_type buckets1 [BucketSize]; + typename unordered_type::bucket_type buckets2 [2]; + typename unordered_type::bucket_type buckets3 [BucketSize*2]; + + unordered_type testset1(&values[0], &values[0] + 6, bucket_traits( + pointer_traits:: + pointer_to(buckets1[0]), BucketSize)); + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + + testset1.rehash(bucket_traits( + pointer_traits:: + pointer_to(buckets2[0]), 2)); + { int init_values [] = { 4, 2, 2, 5, 3, 1 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + + testset1.rehash(bucket_traits( + pointer_traits:: + pointer_to(buckets3[0]), BucketSize*2)); + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + + //Now rehash reducing the buckets + testset1.rehash(bucket_traits( + pointer_traits:: + pointer_to(buckets3[0]), 2)); + { int init_values [] = { 4, 2, 2, 5, 3, 1 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + + //Now rehash increasing the buckets + testset1.rehash(bucket_traits( + pointer_traits:: + pointer_to(buckets3[0]), BucketSize*2)); + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } +} + +//test: find, equal_range (lower_bound, upper_bound): +template +void test_unordered:: + test_find(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + + typedef typename unordered_type::bucket_traits bucket_traits; + typedef typename unordered_type::key_of_value key_of_value; + const bool is_multikey = boost::intrusive::test::is_multikey_true::value; + + typename unordered_type::bucket_type buckets[BucketSize]; + unordered_type testset(values.begin(), values.end(), bucket_traits( + pointer_traits:: + pointer_to(buckets[0]), BucketSize)); + + typedef typename unordered_type::iterator iterator; + + value_type cmp_val; + cmp_val.value_ = 2; + BOOST_TEST (testset.count(key_of_value()(cmp_val)) == (is_multikey ? 2 : 1)); + iterator i = testset.find (key_of_value()(cmp_val)); + BOOST_TEST (i->value_ == 2); + if(is_multikey) + BOOST_TEST ((++i)->value_ == 2); + else + BOOST_TEST ((++i)->value_ != 2); + std::pair range = testset.equal_range (key_of_value()(cmp_val)); + + BOOST_TEST (range.first->value_ == 2); + BOOST_TEST (range.second->value_ == 3); + BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == (is_multikey ? 2 : 1)); + cmp_val.value_ = 7; + BOOST_TEST (testset.find (key_of_value()(cmp_val)) == testset.end()); + BOOST_TEST (testset.count(key_of_value()(cmp_val)) == 0); +} + + +template +void test_unordered + ::test_clone(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + typedef std::multiset std_multiset_t; + + typedef typename unordered_type::bucket_traits bucket_traits; + { + //Test with equal bucket arrays + typename unordered_type::bucket_type buckets1 [BucketSize]; + typename unordered_type::bucket_type buckets2 [BucketSize]; + unordered_type testset1 (values.begin(), values.end(), bucket_traits( + pointer_traits:: + pointer_to(buckets1[0]), BucketSize)); + unordered_type testset2 (bucket_traits( + pointer_traits:: + pointer_to(buckets2[0]), BucketSize)); + + testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer()); + BOOST_TEST(testset1 == testset2); + //Ordering is not guarantee in the cloning so insert data in a set and test + std_multiset_t src(testset1.begin(), testset1.end()); + std_multiset_t dst(testset2.begin(), testset2.end()); + BOOST_TEST (src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin())); + testset2.clear_and_dispose(test::delete_disposer()); + BOOST_TEST (testset2.empty()); + + testset2.clone_from(boost::move(testset1), test::new_nonconst_cloner(), test::delete_disposer()); + BOOST_TEST(testset1 == testset2); + //Ordering is not guarantee in the cloning so insert data in a set and test + std_multiset_t(testset1.begin(), testset1.end()).swap(src); + std_multiset_t(testset2.begin(), testset2.end()).swap(dst); + BOOST_TEST(src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin())); + testset2.clear_and_dispose(test::delete_disposer()); + BOOST_TEST (testset2.empty()); + } + { + //Test with bigger source bucket arrays + typename unordered_type::bucket_type buckets1 [BucketSize*2]; + typename unordered_type::bucket_type buckets2 [BucketSize]; + unordered_type testset1 (values.begin(), values.end(), bucket_traits( + pointer_traits:: + pointer_to(buckets1[0]), BucketSize*2)); + unordered_type testset2 (bucket_traits( + pointer_traits:: + pointer_to(buckets2[0]), BucketSize)); + + testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer()); + BOOST_TEST(testset1 == testset2); + //Ordering is not guarantee in the cloning so insert data in a set and test + std_multiset_t src(testset1.begin(), testset1.end()); + std_multiset_t dst(testset2.begin(), testset2.end()); + BOOST_TEST (src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin())); + testset2.clear_and_dispose(test::delete_disposer()); + BOOST_TEST (testset2.empty()); + + testset2.clone_from(boost::move(testset1), test::new_nonconst_cloner(), test::delete_disposer()); + BOOST_TEST(testset1 == testset2); + //Ordering is not guarantee in the cloning so insert data in a set and test + std_multiset_t(testset1.begin(), testset1.end()).swap(src); + std_multiset_t(testset2.begin(), testset2.end()).swap(dst); + BOOST_TEST (src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin())); + testset2.clear_and_dispose(test::delete_disposer()); + BOOST_TEST (testset2.empty()); + } + { + //Test with smaller source bucket arrays + typename unordered_type::bucket_type buckets1 [BucketSize]; + typename unordered_type::bucket_type buckets2 [BucketSize*2]; + unordered_type testset1 (values.begin(), values.end(), bucket_traits( + pointer_traits:: + pointer_to(buckets1[0]), BucketSize)); + unordered_type testset2 (bucket_traits( + pointer_traits:: + pointer_to(buckets2[0]), BucketSize*2)); + + testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer()); + BOOST_TEST(testset1 == testset2); + //Ordering is not guaranteed in the cloning so insert data in a set and test + std_multiset_t src(testset1.begin(), testset1.end()); + std_multiset_t dst(testset2.begin(), testset2.end()); + BOOST_TEST (src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin())); + testset2.clear_and_dispose(test::delete_disposer()); + BOOST_TEST (testset2.empty()); + + testset2.clone_from(boost::move(testset1), test::new_nonconst_cloner(), test::delete_disposer()); + BOOST_TEST(testset1 == testset2); + //Ordering is not guaranteed in the cloning so insert data in a set and test + std_multiset_t(testset1.begin(), testset1.end()).swap(src); + std_multiset_t(testset2.begin(), testset2.end()).swap(dst); + BOOST_TEST (src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin())); + testset2.clear_and_dispose(test::delete_disposer()); + BOOST_TEST (testset2.empty()); + } +} + +} //namespace test{ +} //namespace intrusive{ +} //namespace boost{ +/* +template < class ValueTraits, bool ConstantTimeSize, bool CacheBegin, bool CompareHash, bool Incremental, bool Map, bool DefaultHolder > +struct rebinder +{ + typedef unordered_rebinder_common common_t; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef unordered_multiset + < typename common_t::value_type + , value_traits + , constant_time_size + , cache_begin + , compare_hash + , incremental + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester::value)); + }; +}; + +template +class test_main_template +{ + public: + static void execute() + { + typedef testvalue > value_type; + static const int random_init[6] = { 3, 2, 4, 1, 5, 2 }; + typedef typename ValueContainer< value_type >::type value_cont_type; + value_cont_type data (6); + for (int i = 0; i < 6; ++i) + data[i].value_ = random_init[i]; + + typedef testvalue_traits< unordered_hooks > testval_traits_t; + //base + typedef typename detail::if_c + < ConstantTimeSize + , typename testval_traits_t::base_value_traits + , typename testval_traits_t::auto_base_value_traits //store_hash + >::type base_hook_t; + test::test_unordered_multiset + < base_hook_t //cache_begin, compare_hash, incremental + , rebinder + >::test_all(data); + //member + typedef typename detail::if_c + < ConstantTimeSize + , typename testval_traits_t::member_value_traits //optimize_multikey + , typename testval_traits_t::auto_member_value_traits //store_hash, optimize_multikey + >::type member_hook_t; + test::test_unordered_multiset + < member_hook_t //cache_begin, compare_hash, incremental + , rebinder + >::test_all(data); + //nonmember + test::test_unordered_multiset + < typename testval_traits_t::nonhook_value_traits //cache_begin, compare_hash, incremental + , rebinder + >::test_all(data); + } +}; + +int main() +{ + //VoidPointer x ConstantTimeSize x Map x DefaultHolder + + //void pointer + test_main_template::execute(); + test_main_template::execute(); + test_main_template::execute(); + test_main_template::execute(); + + //smart_ptr + test_main_template, false, false, false>::execute(); + test_main_template, false, true, false>::execute(); + test_main_template, true, false, false>::execute(); + test_main_template, true, true, false>::execute(); + + ////bounded_ptr (bool ConstantTimeSize, bool Map) + //test_main_template_bptr< false, false >::execute(); + //test_main_template_bptr< false, true >::execute(); + //test_main_template_bptr< true, false >::execute(); + test_main_template_bptr< true, true >::execute(); + + return boost::report_errors(); +} +*/ + diff --git a/test/unordered_test_common.hpp b/test/unordered_test_common.hpp new file mode 100644 index 0000000..385b39d --- /dev/null +++ b/test/unordered_test_common.hpp @@ -0,0 +1,69 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2015-2015. +// +// 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 http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_TEST_UNORDERED_TEST_COMMON_HPP +#define BOOST_INTRUSIVE_TEST_UNORDERED_TEST_COMMON_HPP + +#include +#include +#include "bptr_value.hpp" +#include "test_common.hpp" + +namespace boost { +namespace intrusive { + +template +struct unordered_hooks +{ + typedef unordered_set_base_hook > base_hook_type; + typedef unordered_set_base_hook + < link_mode + , void_pointer + , tag + , store_hash + > auto_base_hook_type; + + typedef unordered_set_member_hook + < void_pointer + , optimize_multikey + > member_hook_type; + typedef unordered_set_member_hook + < link_mode, void_pointer + , store_hash + , optimize_multikey + > auto_member_hook_type; + typedef nonhook_node_member< unordered_node_traits< VoidPointer, true, true >, + unordered_algorithms + > nonhook_node_member_type; +}; + +template < class ValueTraits, bool DefaultHolder, bool Map > +struct unordered_rebinder_common +{ + typedef typename ValueTraits::value_type value_type; + typedef typename detail::if_c + < DefaultHolder + , typename detail::if_c + < detail::is_same::value + , header_holder_type< bounded_pointer_holder< BPtr_Value > > + , void + >::type + , header_holder_type< heap_node_holder< typename ValueTraits::node_ptr > > + >::type holder_opt; + typedef typename detail::if_c + < Map, key_of_value >, void + >::type key_of_value_opt; +}; + +} //namespace intrusive { +} //namespace boost { + +#endif //BOOST_INTRUSIVE_TEST_UNORDERED_TEST_COMMON_HPP