diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
commit | 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch) | |
tree | e5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/intrusive/test | |
parent | Initial commit. (diff) | |
download | ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.zip |
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/intrusive/test')
54 files changed, 10788 insertions, 0 deletions
diff --git a/src/boost/libs/intrusive/test/Jamfile.v2 b/src/boost/libs/intrusive/test/Jamfile.v2 new file mode 100644 index 00000000..8193d27a --- /dev/null +++ b/src/boost/libs/intrusive/test/Jamfile.v2 @@ -0,0 +1,34 @@ +# Boost Intrusive Library Test Jamfile +# (C) Copyright Ion Gaztanaga 2006. +# Use, modification and distribution are subject to 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) + +# Adapted from John Maddock's TR1 Jamfile.v2 +# Copyright John Maddock 2005. +# Use, modification and distribution are subject to 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) + +# this rule enumerates through all the sources and invokes +# the run rule for each source, the result is a list of all +# the run rules, which we can pass on to the test_suite rule: + +rule test_all +{ + local all_rules = ; + + for local fileb in [ glob *.cpp ] + { + all_rules += [ run $(fileb) + : # additional args + : # test-files + : # requirements + <host-os>windows,<toolset>clang:<linkflags>"-lole32 -loleaut32 -lpsapi -ladvapi32" + ] ; + } + + return $(all_rules) ; +} + +test-suite intrusive_test : [ test_all r ] : ;
\ No newline at end of file diff --git a/src/boost/libs/intrusive/test/any_test.cpp b/src/boost/libs/intrusive/test/any_test.cpp new file mode 100644 index 00000000..75528993 --- /dev/null +++ b/src/boost/libs/intrusive/test/any_test.cpp @@ -0,0 +1,188 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2013. +// +// 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<boost/intrusive/any_hook.hpp> +#include<boost/intrusive/slist.hpp> +#include<boost/intrusive/rbtree.hpp> +#include<boost/intrusive/list.hpp> +#include<boost/intrusive/avltree.hpp> +#include<boost/intrusive/sgtree.hpp> +#include<boost/intrusive/splaytree.hpp> +#include<boost/intrusive/treap.hpp> +#include<boost/intrusive/hashtable.hpp> +#include<boost/functional/hash.hpp> +#include <vector> //std::vector +#include <cstddef> //std::size_t + +using namespace boost::intrusive; + +class MyClass : public any_base_hook<> +{ + int int_; + + public: + //This is a member hook + any_member_hook<> member_hook_; + + MyClass(int i = 0) + : int_(i) + {} + + int get() const + { return this->int_; } + + friend bool operator < (const MyClass &l, const MyClass &r) + { return l.int_ < r.int_; } + + friend bool operator == (const MyClass &l, const MyClass &r) + { return l.int_ == r.int_; } + + friend std::size_t hash_value(const MyClass &o) + { return boost::hash<int>()(o.get()); } + + friend bool priority_order(const MyClass &a, const MyClass &b) + { return a.int_ < b.int_; } +}; + + +void instantiation_test() +{ + typedef member_hook< MyClass, any_member_hook<>, &MyClass::member_hook_> MemberHook; + typedef base_hook< any_base_hook<> > BaseHook; + + MyClass myclass; + { + slist < MyClass, any_to_slist_hook< BaseHook > > slist_base; + slist_base.push_front(myclass); + } + { + slist < MyClass, any_to_slist_hook< MemberHook > > slist_member; + slist_member.push_front(myclass); + } + { + list < MyClass, any_to_list_hook< BaseHook > > list_base; + list_base.push_front(myclass); + } + { + list < MyClass, any_to_list_hook< MemberHook > > list_member; + list_member.push_front(myclass); + } + { + rbtree < MyClass, any_to_set_hook< BaseHook > > rbtree_base; + rbtree_base.insert_unique(myclass); + } + { + rbtree < MyClass, any_to_set_hook< MemberHook > > rbtree_member; + rbtree_member.insert_unique(myclass); + } + { + avltree < MyClass, any_to_avl_set_hook< BaseHook > > avltree_base; + avltree_base.insert_unique(myclass); + } + { + avltree < MyClass, any_to_avl_set_hook< MemberHook > > avltree_member; + avltree_member.insert_unique(myclass); + } + { + sgtree < MyClass, any_to_bs_set_hook< BaseHook > > sgtree_base; + sgtree_base.insert_unique(myclass); + } + { + sgtree < MyClass, any_to_bs_set_hook< MemberHook > > sgtree_member; + sgtree_member.insert_unique(myclass); + } + { + treap < MyClass, any_to_bs_set_hook< BaseHook > > treap_base; + treap_base.insert_unique(myclass); + } + { + treap < MyClass, any_to_bs_set_hook< MemberHook > > treap_member; + treap_member.insert_unique(myclass); + } + { + splaytree < MyClass, any_to_bs_set_hook< BaseHook > > splaytree_base; + splaytree_base.insert_unique(myclass); + } + { + splaytree < MyClass, any_to_bs_set_hook< MemberHook > > splaytree_member; + splaytree_member.insert_unique(myclass); + } + typedef unordered_bucket<any_to_unordered_set_hook< BaseHook > >::type bucket_type; + typedef unordered_default_bucket_traits<any_to_unordered_set_hook< BaseHook > >::type bucket_traits; + bucket_type buckets[2]; + { + hashtable < MyClass, any_to_unordered_set_hook< BaseHook > > + hashtable_base(bucket_traits(&buckets[0], 1)); + hashtable_base.insert_unique(myclass); + } + { + hashtable < MyClass, any_to_unordered_set_hook< MemberHook > > + hashtable_member(bucket_traits(&buckets[1], 1)); + hashtable_member.insert_unique(myclass); + } +} + +bool simple_slist_test() +{ + //Define an slist that will store MyClass using the public base hook + typedef any_to_slist_hook< base_hook< any_base_hook<> > >BaseOption; + typedef slist<MyClass, BaseOption, constant_time_size<false> > BaseList; + + //Define an slist that will store MyClass using the public member hook + typedef any_to_slist_hook< member_hook<MyClass, any_member_hook<>, &MyClass::member_hook_> > MemberOption; + typedef slist<MyClass, MemberOption> MemberList; + + typedef std::vector<MyClass>::iterator VectIt; + typedef std::vector<MyClass>::reverse_iterator VectRit; + + //Create several MyClass objects, each one with a different value + std::vector<MyClass> values; + for(int i = 0; i < 100; ++i) values.push_back(MyClass(i)); + + BaseList baselist; + MemberList memberlist; + + //Now insert them in the reverse order in the base hook list + for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it) + baselist.push_front(*it); + + //Now insert them in the same order as in vector in the member hook list + for(BaseList::iterator it(baselist.begin()), itend(baselist.end()) + ; it != itend; ++it){ + memberlist.push_front(*it); + } + + //Now test lists + { + BaseList::iterator bit(baselist.begin()); + MemberList::iterator mit(memberlist.begin()); + VectRit rit(values.rbegin()), ritend(values.rend()); + VectIt it(values.begin()), itend(values.end()); + + //Test the objects inserted in the base hook list + for(; rit != ritend; ++rit, ++bit) + if(&*bit != &*rit) return false; + + //Test the objects inserted in the member hook list + for(; it != itend; ++it, ++mit) + if(&*mit != &*it) return false; + } + return true; +} + +int main() +{ + if(!simple_slist_test()) + return 1; + instantiation_test(); + return 0; +} diff --git a/src/boost/libs/intrusive/test/avl_multiset_test.cpp b/src/boost/libs/intrusive/test/avl_multiset_test.cpp new file mode 100644 index 00000000..c2dce57d --- /dev/null +++ b/src/boost/libs/intrusive/test/avl_multiset_test.cpp @@ -0,0 +1,156 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (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 <boost/intrusive/avl_set.hpp> +#include "itestvalue.hpp" +#include "bptr_value.hpp" +#include "smart_ptr.hpp" +#include "avl_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<ValueTraits, DefaultHolder, Map> common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef avl_multiset + < typename common_t::value_type + , value_traits<ValueTraits> + , constant_time_size<ConstantTimeSize> + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value)); + }; +}; + +enum HookType +{ + Base, + Member, + NonMember +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type> +class test_main_template; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base> +{ + public: + static void execute() + { + typedef testvalue_traits< avl_hooks<VoidPointer> > 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 + < rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member> +{ + public: + static void execute() + { + typedef testvalue_traits< avl_hooks<VoidPointer> > testval_traits_t; + //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 + < rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember> +{ + public: + static void execute() + { + typedef testvalue_traits< avl_hooks<VoidPointer> > testval_traits_t; + //nonmember + test::test_generic_multiset + < rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template < bool ConstantTimeSize, bool Map > +struct test_main_template_bptr +{ + static void execute() + { + typedef BPtr_Value_Traits< AVLTree_BPtr_Node_Traits > value_traits; + typedef bounded_allocator< BPtr_Value > allocator_type; + + bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope; + test::test_generic_multiset + < 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<void*, false, false, false, Base>::execute(); + //test_main_template<void*, false, false, true>::execute(); + test_main_template<void*, false, true, false, Member>::execute(); + //test_main_template<void*, false, true, true>::execute(); + test_main_template<void*, true, false, false, Base>::execute(); + //test_main_template<void*, true, false, true>::execute(); + test_main_template<void*, true, true, false, Member>::execute(); + test_main_template<void*, true, true, true, NonMember>::execute(); + + //smart_ptr + //test_main_template<smart_ptr<void>, false, false, false>::execute(); + test_main_template<smart_ptr<void>, false, false, true, Base>::execute(); + //test_main_template<smart_ptr<void>, false, true, false>::execute(); + test_main_template<smart_ptr<void>, false, true, true, Member>::execute(); + //test_main_template<smart_ptr<void>, true, false, false>::execute(); + test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute(); + //test_main_template<smart_ptr<void>, true, true, false>::execute(); + //test_main_template<smart_ptr<void>, 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/src/boost/libs/intrusive/test/avl_set_test.cpp b/src/boost/libs/intrusive/test/avl_set_test.cpp new file mode 100644 index 00000000..677232b1 --- /dev/null +++ b/src/boost/libs/intrusive/test/avl_set_test.cpp @@ -0,0 +1,156 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (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 <boost/intrusive/avl_set.hpp> +#include "itestvalue.hpp" +#include "bptr_value.hpp" +#include "smart_ptr.hpp" +#include "avl_test_common.hpp" +#include "generic_set_test.hpp" + +using namespace boost::intrusive; + +template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map > +struct rebinder +{ + typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef avl_set + < typename common_t::value_type + , value_traits<ValueTraits> + , constant_time_size<ConstantTimeSize> + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value)); + }; +}; + +enum HookType +{ + Base, + Member, + NonMember +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type> +class test_main_template; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base> +{ + public: + static void execute() + { + typedef testvalue_traits< avl_hooks<VoidPointer> > 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 + < rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member> +{ + public: + static void execute() + { + typedef testvalue_traits< avl_hooks<VoidPointer> > testval_traits_t; + //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 + < rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember> +{ + public: + static void execute() + { + typedef testvalue_traits< avl_hooks<VoidPointer> > testval_traits_t; + //nonmember + test::test_generic_set + < rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template < bool ConstantTimeSize, bool Map > +struct test_main_template_bptr +{ + static void execute() + { + typedef BPtr_Value_Traits< AVLTree_BPtr_Node_Traits > value_traits; + typedef bounded_allocator< BPtr_Value > allocator_type; + + bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope; + test::test_generic_set + < 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<void*, false, false, false, Base>::execute(); + //test_main_template<void*, false, false, true>::execute(); + test_main_template<void*, false, true, false, Member>::execute(); + //test_main_template<void*, false, true, true>::execute(); + test_main_template<void*, true, false, false, Base>::execute(); + //test_main_template<void*, true, false, true>::execute(); + test_main_template<void*, true, true, false, Member>::execute(); + test_main_template<void*, true, true, true, NonMember>::execute(); + + //smart_ptr + //test_main_template<smart_ptr<void>, false, false, false>::execute(); + test_main_template<smart_ptr<void>, false, false, true, Base>::execute(); + //test_main_template<smart_ptr<void>, false, true, false>::execute(); + test_main_template<smart_ptr<void>, false, true, true, Member>::execute(); + //test_main_template<smart_ptr<void>, true, false, false>::execute(); + test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute(); + //test_main_template<smart_ptr<void>, true, true, false>::execute(); + //test_main_template<smart_ptr<void>, 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/src/boost/libs/intrusive/test/avl_test_common.hpp b/src/boost/libs/intrusive/test/avl_test_common.hpp new file mode 100644 index 00000000..eed1659d --- /dev/null +++ b/src/boost/libs/intrusive/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 <boost/intrusive/avl_set_hook.hpp> +#include <boost/intrusive/detail/mpl.hpp> +#include "bs_test_common.hpp" + +namespace boost { +namespace intrusive { + +template<class VoidPointer> +struct avl_hooks +{ + typedef avl_set_base_hook<void_pointer<VoidPointer> > base_hook_type; + typedef avl_set_base_hook + <link_mode<auto_unlink> + , void_pointer<VoidPointer> + , tag<void> + , optimize_size<true> > auto_base_hook_type; + typedef avl_set_member_hook + <void_pointer<VoidPointer> + , optimize_size<true> > member_hook_type; + typedef avl_set_member_hook + < link_mode<auto_unlink> + , void_pointer<VoidPointer> > auto_member_hook_type; + typedef nonhook_node_member< avltree_node_traits<VoidPointer>, + avltree_algorithms + > nonhook_node_member_type; +}; + +} //namespace intrusive { +} //namespace boost { + +#endif //BOOST_INTRUSIVE_TEST_AVL_TEST_COMMON_HPP diff --git a/src/boost/libs/intrusive/test/bounded_pointer.hpp b/src/boost/libs/intrusive/test/bounded_pointer.hpp new file mode 100644 index 00000000..008c414d --- /dev/null +++ b/src/boost/libs/intrusive/test/bounded_pointer.hpp @@ -0,0 +1,429 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Matei David 2014 +// +// 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 BOUNDED_POINTER_HPP +#define BOUNDED_POINTER_HPP + +#include <iostream> +#include <cstdlib> +#include <cassert> +#include <boost/container/vector.hpp> +#include <boost/intrusive/detail/mpl.hpp> +#include <boost/intrusive/pointer_traits.hpp> +#include <boost/core/no_exceptions_support.hpp> +#include <boost/move/adl_move_swap.hpp> + +template < typename T > +class bounded_pointer; + +template < typename T > +class bounded_reference; + +template < typename T > +class bounded_allocator; + + +template < typename T > +class bounded_pointer +{ + private: + void unspecified_bool_type_func() const {} + typedef void (bounded_pointer::*unspecified_bool_type)() const; + + public: + typedef typename boost::intrusive::detail::remove_const< T >::type mut_val_t; + typedef const mut_val_t const_val_t; + + typedef bounded_reference<T> reference; + + static const unsigned char max_offset = (unsigned char)-1; + + bounded_pointer() : m_offset(max_offset) {} + + bounded_pointer(const bounded_pointer& other) + : m_offset(other.m_offset) + {} + + template<class T2> + bounded_pointer( const bounded_pointer<T2> &other + , typename boost::intrusive::detail::enable_if_convertible<T2*, T*>::type* = 0) + : m_offset(other.m_offset) + {} + + bounded_pointer& operator = (const bounded_pointer& other) + { m_offset = other.m_offset; return *this; } + + template <class T2> + typename boost::intrusive::detail::enable_if_convertible<T2*, T*, bounded_pointer&>::type + operator= (const bounded_pointer<T2> & other) + { m_offset = other.m_offset; return *this; } + + const bounded_pointer< typename boost::intrusive::detail::remove_const< T >::type >& unconst() const + { return *reinterpret_cast< const bounded_pointer< typename boost::intrusive::detail::remove_const< T >::type >* >(this); } + + bounded_pointer< typename boost::intrusive::detail::remove_const< T >::type >& unconst() + { return *reinterpret_cast< bounded_pointer< typename boost::intrusive::detail::remove_const< T >::type >* >(this); } + + static mut_val_t* base() + { + assert(bounded_allocator< mut_val_t >::inited()); + return &bounded_allocator< mut_val_t >::m_base[0]; + } + + static bounded_pointer pointer_to(bounded_reference< T > r) { return &r; } + + template<class U> + static bounded_pointer const_cast_from(const bounded_pointer<U> &uptr) + { return uptr.unconst(); } + + operator unspecified_bool_type() const + { + return m_offset != max_offset? &bounded_pointer::unspecified_bool_type_func : 0; + } + + T* raw() const + { return base() + m_offset; } + + bounded_reference< T > operator * () const + { return bounded_reference< T >(*this); } + + T* operator -> () const + { return raw(); } + + bounded_pointer& operator ++ () + { ++m_offset; return *this; } + + bounded_pointer operator ++ (int) + { bounded_pointer res(*this); ++(*this); return res; } + + friend bool operator == (const bounded_pointer& lhs, const bounded_pointer& rhs) + { return lhs.m_offset == rhs.m_offset; } + + friend bool operator != (const bounded_pointer& lhs, const bounded_pointer& rhs) + { return lhs.m_offset != rhs.m_offset; } + + friend bool operator < (const bounded_pointer& lhs, const bounded_pointer& rhs) + { return lhs.m_offset < rhs.m_offset; } + + friend bool operator <= (const bounded_pointer& lhs, const bounded_pointer& rhs) + { return lhs.m_offset <= rhs.m_offset; } + + friend bool operator >= (const bounded_pointer& lhs, const bounded_pointer& rhs) + { return lhs.m_offset >= rhs.m_offset; } + + friend bool operator > (const bounded_pointer& lhs, const bounded_pointer& rhs) + { return lhs.m_offset > rhs.m_offset; } + + friend std::ostream& operator << (std::ostream& os, const bounded_pointer& ptr) + { + os << static_cast< int >(ptr.m_offset); + return os; + } + private: + + template <typename> friend class bounded_pointer; + friend class bounded_reference< T >; + friend class bounded_allocator< T >; + + unsigned char m_offset; +}; // class bounded_pointer + +template < typename T > +class bounded_reference +{ + public: + typedef typename boost::intrusive::detail::remove_const< T >::type mut_val_t; + typedef const mut_val_t const_val_t; + typedef bounded_pointer< T > pointer; + static const unsigned char max_offset = pointer::max_offset; + + + bounded_reference() + : m_offset(max_offset) + {} + + bounded_reference(const bounded_reference& other) + : m_offset(other.m_offset) + {} + + T& raw() const + { assert(m_offset != max_offset); return *(bounded_pointer< T >::base() + m_offset); } + + operator T& () const + { assert(m_offset != max_offset); return raw(); } + + bounded_pointer< T > operator & () const + { assert(m_offset != max_offset); bounded_pointer< T > res; res.m_offset = m_offset; return res; } + + bounded_reference& operator = (const T& rhs) + { assert(m_offset != max_offset); raw() = rhs; return *this; } + + bounded_reference& operator = (const bounded_reference& rhs) + { assert(m_offset != max_offset); raw() = rhs.raw(); return *this; } + + template<class T2> + bounded_reference( const bounded_reference<T2> &other + , typename boost::intrusive::detail::enable_if_convertible<T2*, T*>::type* = 0) + : m_offset(other.m_offset) + {} + + template <class T2> + typename boost::intrusive::detail::enable_if_convertible<T2*, T*, bounded_reference&>::type + operator= (const bounded_reference<T2> & other) + { m_offset = other.m_offset; return *this; } + + friend std::ostream& operator << (std::ostream& os, const bounded_reference< T >& ref) + { + os << "[bptr=" << static_cast< int >(ref.m_offset) << ",deref=" << ref.raw() << "]"; + return os; + } + + // the copy asop is shallow; we need swap overload to shuffle a vector of references + friend void swap(bounded_reference& lhs, bounded_reference& rhs) + { ::boost::adl_move_swap(lhs.m_offset, rhs.m_offset); } + + private: + template <typename> friend class bounded_reference; + friend class bounded_pointer< T >; + bounded_reference(bounded_pointer< T > bptr) : m_offset(bptr.m_offset) { assert(m_offset != max_offset); } + + unsigned char m_offset; +}; // class bounded_reference + +template < typename T > +class bounded_allocator +{ + public: + typedef T value_type; + typedef bounded_pointer< T > pointer; + + static const unsigned char max_offset = pointer::max_offset; + + pointer allocate(size_t n) + { + assert(inited()); + assert(n == 1);(void)n; + pointer p; + unsigned char i; + for (i = 0; i < max_offset && m_in_use[i]; ++i); + assert(i < max_offset); + p.m_offset = i; + m_in_use[p.m_offset] = true; + ++m_in_use_count; + return p; + } + + void deallocate(pointer p, size_t n) + { + assert(inited()); + assert(n == 1);(void)n; + assert(m_in_use[p.m_offset]); + m_in_use[p.m_offset] = false; + --m_in_use_count; + } + + // static methods + static void init() + { + assert(m_in_use.empty()); + m_in_use = boost::container::vector< bool >(max_offset, false); + // allocate non-constructed storage + m_base = static_cast< T* >(::operator new [] (max_offset * sizeof(T))); + } + + static bool inited() + { + return m_in_use.size() == max_offset; + } + + static bool is_clear() + { + assert(inited()); + for (unsigned char i = 0; i < max_offset; ++i) + { + if (m_in_use[i]) + { + return false; + } + } + return true; + } + + static void destroy() + { + // deallocate storage without destructors + ::operator delete [] (m_base); + m_in_use.clear(); + } + + private: + friend class bounded_pointer< T >; + friend class bounded_pointer< const T >; + static T* m_base; + static boost::container::vector< bool > m_in_use; + static std::size_t m_in_use_count; +}; // class bounded_allocator + +template <class BoundedAllocator> +class bounded_allocator_scope +{ + public: + bounded_allocator_scope() + { BoundedAllocator::init(); } + + ~bounded_allocator_scope() + { + assert(BoundedAllocator::is_clear()); + BoundedAllocator::destroy(); + } +}; + +template < typename T > +T* bounded_allocator< T >::m_base = 0; + +template < typename T > +boost::container::vector< bool > bounded_allocator< T >::m_in_use; + +template < typename T > +std::size_t bounded_allocator< T >::m_in_use_count; + +template < typename T > +class bounded_reference_cont + : private boost::container::vector< bounded_reference< T > > +{ + private: + typedef T val_type; + typedef boost::container::vector< bounded_reference< T > > Base; + typedef bounded_allocator< T > allocator_type; + typedef bounded_pointer< T > pointer; + + public: + typedef typename Base::value_type value_type; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + typedef typename Base::reference reference; + typedef typename Base::const_reference const_reference; + typedef typename Base::reverse_iterator reverse_iterator; + typedef typename Base::const_reverse_iterator const_reverse_iterator; + + using Base::begin; + using Base::rbegin; + using Base::end; + using Base::rend; + using Base::front; + using Base::back; + using Base::size; + using Base::operator[]; + using Base::push_back; + + explicit bounded_reference_cont(size_t n = 0) + : Base(), m_allocator() + { + for (size_t i = 0; i < n; ++i){ + pointer p = m_allocator.allocate(1); + BOOST_TRY{ + new (p.raw()) val_type(); + } + BOOST_CATCH(...){ + m_allocator.deallocate(p, 1); + BOOST_RETHROW + } + BOOST_CATCH_END + Base::push_back(*p); + } + } + + bounded_reference_cont(const bounded_reference_cont& other) + : Base(), m_allocator(other.m_allocator) + { *this = other; } + + template < typename InputIterator > + bounded_reference_cont(InputIterator it_start, InputIterator it_end) + : Base(), m_allocator() + { + for (InputIterator it = it_start; it != it_end; ++it){ + pointer p = m_allocator.allocate(1); + new (p.raw()) val_type(*it); + Base::push_back(*p); + } + } + + template <typename InputIterator> + void assign(InputIterator it_start, InputIterator it_end) + { + this->clear(); + for (InputIterator it = it_start; it != it_end;){ + pointer p = m_allocator.allocate(1); + new (p.raw()) val_type(*it++); + Base::push_back(*p); + } + } + + ~bounded_reference_cont() + { clear(); } + + void clear() + { + while (!Base::empty()){ + pointer p = &Base::back(); + p->~val_type(); + m_allocator.deallocate(p, 1); + Base::pop_back(); + } + } + + bounded_reference_cont& operator = (const bounded_reference_cont& other) + { + if (&other != this){ + clear(); + for (typename Base::const_iterator it = other.begin(); it != other.end(); ++it){ + pointer p = m_allocator.allocate(1); + new (p.raw()) val_type(*it); + Base::push_back(*p); + } + } + return *this; + } + + private: + allocator_type m_allocator; +}; // class bounded_reference_cont + +template < typename T > +class bounded_pointer_holder +{ + public: + typedef T value_type; + typedef bounded_pointer< value_type > pointer; + typedef bounded_pointer< const value_type > const_pointer; + typedef bounded_allocator< value_type > allocator_type; + + bounded_pointer_holder() : _ptr(allocator_type().allocate(1)) + { new (_ptr.raw()) value_type(); } + + ~bounded_pointer_holder() + { + _ptr->~value_type(); + allocator_type().deallocate(_ptr, 1); + } + + const_pointer get_node () const + { return _ptr; } + + pointer get_node () + { return _ptr; } + + private: + const pointer _ptr; +}; // class bounded_pointer_holder + +#endif diff --git a/src/boost/libs/intrusive/test/bptr_value.hpp b/src/boost/libs/intrusive/test/bptr_value.hpp new file mode 100644 index 00000000..d4313c57 --- /dev/null +++ b/src/boost/libs/intrusive/test/bptr_value.hpp @@ -0,0 +1,270 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Matei David 2014 +// (C) Copyright Ion Gaztanaga 2014 +// +// 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_BPTR_VALUE_HPP +#define BOOST_INTRUSIVE_BPTR_VALUE_HPP + +#include <cassert> +#include <iostream> +#include "bounded_pointer.hpp" +#include "common_functors.hpp" +#include "int_holder.hpp" +#include <boost/intrusive/link_mode.hpp> + + +namespace boost { +namespace intrusive { + +struct BPtr_Value +{ + static const bool constant_time_size = true; + + explicit BPtr_Value(int value = 42) + : value_(value) + {} + + BPtr_Value(const BPtr_Value& rhs) + : value_(rhs.value_) + {} + + ~BPtr_Value() + { + if (is_linked()) + { + assert(false); + } + } + + // testvalue is used in boost::container::vector and thus prev and next + // have to be handled appropriately when copied: + BPtr_Value& operator = (const BPtr_Value& src) + { + if (is_linked()) + { + assert(false); + } + value_ = src.value_; + return *this; + } + + // value + int_holder value_; + + // list node hooks + bounded_pointer< BPtr_Value > m_previous; + bounded_pointer< BPtr_Value > m_next; + // tree node hooks + bounded_pointer< BPtr_Value > m_parent; + bounded_pointer< BPtr_Value > m_l_child; + bounded_pointer< BPtr_Value > m_r_child; + signed char m_extra; + + const int_holder &get_int_holder() const + { return value_; } + + int int_value() const + { return value_.int_value(); } + + bool is_linked() const + { return m_previous || m_next || m_parent || m_l_child || m_r_child; } + + friend bool operator< (const BPtr_Value &other1, const BPtr_Value &other2) + { return other1.value_ < other2.value_; } + + friend bool operator< (int other1, const BPtr_Value &other2) + { return other1 < other2.value_; } + + friend bool operator< (const BPtr_Value &other1, int other2) + { return other1.value_ < other2; } + + friend bool operator> (const BPtr_Value &other1, const BPtr_Value &other2) + { return other1.value_ > other2.value_; } + + friend bool operator> (int other1, const BPtr_Value &other2) + { return other1 > other2.value_; } + + friend bool operator> (const BPtr_Value &other1, int other2) + { return other1.value_ > other2; } + + friend bool operator== (const BPtr_Value &other1, const BPtr_Value &other2) + { return other1.value_ == other2.value_; } + + friend bool operator== (int other1, const BPtr_Value &other2) + { return other1 == other2.value_; } + + friend bool operator== (const BPtr_Value &other1, int other2) + { return other1.value_ == other2; } + + friend bool operator!= (const BPtr_Value &other1, const BPtr_Value &other2) + { return !(other1 == other2); } + + friend bool operator!= (int other1, const BPtr_Value &other2) + { return !(other1 == other2.value_); } + + friend bool operator!= (const BPtr_Value &other1, int other2) + { return !(other1.value_ == other2); } + +}; // class BPtr_Value + +std::ostream& operator<<(std::ostream& s, const BPtr_Value& t) +{ return s << t.value_.int_value(); } + +template < typename Node_Algorithms > +void swap_nodes(bounded_reference< BPtr_Value > lhs, bounded_reference< BPtr_Value > rhs) +{ + Node_Algorithms::swap_nodes( + boost::intrusive::pointer_traits< bounded_pointer< BPtr_Value > >::pointer_to(lhs), + boost::intrusive::pointer_traits< bounded_pointer< BPtr_Value > >::pointer_to(rhs)); +} + +struct List_BPtr_Node_Traits +{ + typedef BPtr_Value val_t; + typedef val_t node; + typedef bounded_pointer< val_t > node_ptr; + typedef bounded_pointer< const val_t > const_node_ptr; + + static node_ptr get_previous(const_node_ptr p) { return p->m_previous; } + static void set_previous(node_ptr p, node_ptr prev) { p->m_previous = prev; } + static node_ptr get_next(const_node_ptr p) { return p->m_next; } + static void set_next(node_ptr p, node_ptr next) { p->m_next = next; } +}; + +struct Tree_BPtr_Node_Traits +{ + typedef BPtr_Value val_t; + typedef val_t node; + typedef bounded_pointer< val_t > node_ptr; + typedef bounded_pointer< const val_t > const_node_ptr; + + static node_ptr get_parent(const_node_ptr p) { return p->m_parent; } + static void set_parent(node_ptr p, node_ptr parent) { p->m_parent = parent; } + static node_ptr get_left(const_node_ptr p) { return p->m_l_child; } + static void set_left(node_ptr p, node_ptr l_child) { p->m_l_child = l_child; } + static node_ptr get_right(const_node_ptr p) { return p->m_r_child; } + static void set_right(node_ptr p, node_ptr r_child) { p->m_r_child = r_child; } +}; + +struct RBTree_BPtr_Node_Traits + : public Tree_BPtr_Node_Traits +{ + typedef signed char color; + typedef Tree_BPtr_Node_Traits::node_ptr node_ptr; + typedef Tree_BPtr_Node_Traits::const_node_ptr const_node_ptr; + static color get_color(const_node_ptr p) { return p->m_extra; } + static void set_color(node_ptr p, color c) { p->m_extra = c; } + static color black() { return 0; } + static color red() { return 1; } +}; + +struct AVLTree_BPtr_Node_Traits + : public Tree_BPtr_Node_Traits +{ + typedef signed char balance; + typedef Tree_BPtr_Node_Traits::node_ptr node_ptr; + typedef Tree_BPtr_Node_Traits::const_node_ptr const_node_ptr; + static balance get_balance(const_node_ptr p) { return p->m_extra; } + static void set_balance(node_ptr p, balance b) { p->m_extra = b; } + static balance negative() { return -1; } + static balance zero() { return 0; } + static balance positive() { return 1; } +}; + +template < typename NodeTraits > +struct BPtr_Value_Traits +{ + typedef NodeTraits node_traits; + typedef typename node_traits::val_t value_type; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; + typedef node_ptr pointer; + typedef const_node_ptr const_pointer; + typedef bounded_reference< value_type > reference; + typedef bounded_reference< const value_type > const_reference; + typedef BPtr_Value_Traits<NodeTraits> * value_traits_ptr; + + static const boost::intrusive::link_mode_type link_mode = boost::intrusive::safe_link; + + static const_node_ptr to_node_ptr(const_reference v) { return &v; } + static node_ptr to_node_ptr(reference v) { return &v; } + static const_pointer to_value_ptr(const_node_ptr p) { return p; } + static pointer to_value_ptr(node_ptr p) { return p; } +}; + +template < typename > +struct ValueContainer; + +template <> +struct ValueContainer< BPtr_Value > +{ + typedef bounded_reference_cont< BPtr_Value > type; +}; + +namespace test{ + +template <> +class new_cloner< BPtr_Value > +{ + public: + typedef BPtr_Value value_type; + typedef bounded_pointer< value_type > pointer; + typedef bounded_reference< const value_type > const_reference; + typedef bounded_allocator< value_type > allocator_type; + + pointer operator () (const_reference r) + { + pointer p = allocator_type().allocate(1); + new (p.raw()) value_type(r); + return p; + } +}; + +template <> +class new_nonconst_cloner< BPtr_Value > +{ + public: + typedef BPtr_Value value_type; + typedef bounded_pointer< value_type > pointer; + typedef bounded_reference< value_type > reference; + typedef bounded_allocator< value_type > allocator_type; + + pointer operator () (reference r) + { + pointer p = allocator_type().allocate(1); + new (p.raw()) value_type(r); + return p; + } +}; + +template <> +class delete_disposer< BPtr_Value > +{ + public: + typedef BPtr_Value value_type; + typedef bounded_pointer< value_type > pointer; + typedef bounded_allocator< value_type > allocator_type; + + void operator () (pointer p) + { + p->~value_type(); + allocator_type().deallocate(p, 1); + } +}; + +} // namespace test + +} // namespace intrusive +} // namespace boost + + +#endif diff --git a/src/boost/libs/intrusive/test/bs_multiset_test.cpp b/src/boost/libs/intrusive/test/bs_multiset_test.cpp new file mode 100644 index 00000000..beb91159 --- /dev/null +++ b/src/boost/libs/intrusive/test/bs_multiset_test.cpp @@ -0,0 +1,157 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (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 <boost/intrusive/bs_set.hpp> +#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<ValueTraits, DefaultHolder, Map> common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef bs_multiset + < typename common_t::value_type + , value_traits<ValueTraits> + , constant_time_size<ConstantTimeSize> + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value)); + }; +}; + +enum HookType +{ + Base, + Member, + NonMember +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type> +class test_main_template; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > 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 + < rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //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 + < rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //nonmember + test::test_generic_multiset + < rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map> + >::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<allocator_type> bounded_scope; (void)bounded_scope; + test::test_generic_multiset + < 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<void*, false, false, false, Base>::execute(); + //test_main_template<void*, false, false, true>::execute(); + test_main_template<void*, false, true, false, Member>::execute(); + //test_main_template<void*, false, true, true>::execute(); + test_main_template<void*, true, false, false, Base>::execute(); + //test_main_template<void*, true, false, true>::execute(); + test_main_template<void*, true, true, false, Member>::execute(); + test_main_template<void*, true, true, true, NonMember>::execute(); + + //smart_ptr + //test_main_template<smart_ptr<void>, false, false, false>::execute(); + test_main_template<smart_ptr<void>, false, false, true, Base>::execute(); + //test_main_template<smart_ptr<void>, false, true, false>::execute(); + test_main_template<smart_ptr<void>, false, true, true, Member>::execute(); + //test_main_template<smart_ptr<void>, true, false, false>::execute(); + test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute(); + //test_main_template<smart_ptr<void>, true, true, false>::execute(); + //test_main_template<smart_ptr<void>, 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(); + //test_main_template_bptr< true, true >::execute(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/intrusive/test/bs_set_test.cpp b/src/boost/libs/intrusive/test/bs_set_test.cpp new file mode 100644 index 00000000..d2f4f4fb --- /dev/null +++ b/src/boost/libs/intrusive/test/bs_set_test.cpp @@ -0,0 +1,155 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (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 <boost/intrusive/bs_set.hpp> +#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<ValueTraits, DefaultHolder, Map> common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef bs_set + < typename common_t::value_type + , value_traits<ValueTraits> + , constant_time_size<ConstantTimeSize> + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value)); + }; +}; + +enum HookType +{ + Base, + Member, + NonMember +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type> +class test_main_template; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > 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 + < rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //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 + < rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //nonmember + test::test_generic_set + < rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map> + >::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<allocator_type> bounded_scope; (void)bounded_scope; + test::test_generic_set + < 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<void*, false, false, false, Base>::execute(); + //test_main_template<void*, false, false, true>::execute(); + test_main_template<void*, false, true, false, Member>::execute(); + //test_main_template<void*, false, true, true>::execute(); + test_main_template<void*, true, false, false, Base>::execute(); + //test_main_template<void*, true, false, true>::execute(); + test_main_template<void*, true, true, false, Member>::execute(); + test_main_template<void*, true, true, true, NonMember>::execute(); + + //smart_ptr + //test_main_template<smart_ptr<void>, false, false, false>::execute(); + test_main_template<smart_ptr<void>, false, false, true, Base>::execute(); + //test_main_template<smart_ptr<void>, false, true, false>::execute(); + test_main_template<smart_ptr<void>, false, true, true, Member>::execute(); + //test_main_template<smart_ptr<void>, true, false, false>::execute(); + test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute(); + //test_main_template<smart_ptr<void>, true, true, false>::execute(); + //test_main_template<smart_ptr<void>, 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/src/boost/libs/intrusive/test/bs_test_common.hpp b/src/boost/libs/intrusive/test/bs_test_common.hpp new file mode 100644 index 00000000..69f7f758 --- /dev/null +++ b/src/boost/libs/intrusive/test/bs_test_common.hpp @@ -0,0 +1,67 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (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 <boost/intrusive/bs_set_hook.hpp> +#include <boost/intrusive/detail/mpl.hpp> +#include "bptr_value.hpp" +#include "test_common.hpp" + +namespace boost { +namespace intrusive { + +template<class VoidPointer> +struct bs_hooks +{ + typedef bs_set_base_hook<void_pointer<VoidPointer> > base_hook_type; + typedef bs_set_base_hook + <link_mode<auto_unlink> + , void_pointer<VoidPointer> + , tag<void> > auto_base_hook_type; + typedef bs_set_member_hook + <void_pointer<VoidPointer> > member_hook_type; + typedef bs_set_member_hook + < link_mode<auto_unlink> + , void_pointer<VoidPointer> > auto_member_hook_type; + typedef nonhook_node_member< tree_node_traits<VoidPointer>, + 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_type, BPtr_Value>::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<int_holder_key_of_value<value_type> >, void + >::type key_of_value_opt; + + typedef typename detail::if_c + < Map, priority_of_value<int_priority_of_value<value_type> >, void + >::type prio_of_value_opt; +}; + + +} //namespace intrusive { +} //namespace boost { + +#endif //BOOST_INTRUSIVE_TEST_BS_TEST_COMMON_HPP diff --git a/src/boost/libs/intrusive/test/common_functors.hpp b/src/boost/libs/intrusive/test/common_functors.hpp new file mode 100644 index 00000000..b84a84a1 --- /dev/null +++ b/src/boost/libs/intrusive/test/common_functors.hpp @@ -0,0 +1,88 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2013 +// +// 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_COMMON_FUNCTORS_HPP +#define BOOST_INTRUSIVE_TEST_COMMON_FUNCTORS_HPP + +#include<boost/intrusive/detail/iterator.hpp> +#include<boost/intrusive/detail/mpl.hpp> +#include<boost/static_assert.hpp> +#include<boost/move/detail/to_raw_pointer.hpp> + +namespace boost { +namespace intrusive { +namespace test { + +template<class T> +class delete_disposer +{ + public: + template <class Pointer> + void operator()(Pointer p) + { + typedef typename boost::intrusive::iterator_traits<Pointer>::value_type value_type; + BOOST_STATIC_ASSERT(( detail::is_same<T, value_type>::value )); + delete boost::movelib::to_raw_pointer(p); + } +}; + +template<class T> +class new_cloner +{ + public: + T *operator()(const T &t) + { return new T(t); } +}; + +template<class T> +class new_nonconst_cloner +{ + public: + T *operator()(T &t) + { return new T(t); } +}; + +template<class T> +class new_default_factory +{ + public: + T *operator()() + { return new T(); } +}; + +class empty_disposer +{ + public: + template<class T> + void operator()(const T &) + {} +}; + +struct any_less +{ + template<class T, class U> + bool operator()(const T &t, const U &u) const + { return t < u; } +}; + +struct any_greater +{ + template<class T, class U> + bool operator()(const T &t, const U &u) const + { return t > u; } +}; + +} //namespace test { +} //namespace intrusive { +} //namespace boost { + +#endif diff --git a/src/boost/libs/intrusive/test/container_size_test.cpp b/src/boost/libs/intrusive/test/container_size_test.cpp new file mode 100644 index 00000000..e320ff5e --- /dev/null +++ b/src/boost/libs/intrusive/test/container_size_test.cpp @@ -0,0 +1,226 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014 +// +// 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 <boost/detail/lightweight_test.hpp> +#include <cstddef> + +#include <boost/intrusive/list.hpp> +#include <boost/intrusive/slist.hpp> +#include <boost/intrusive/set.hpp> +#include <boost/intrusive/avl_set.hpp> +#include <boost/intrusive/bs_set.hpp> +#include <boost/intrusive/sg_set.hpp> +#include <boost/intrusive/splay_set.hpp> +#include <boost/intrusive/treap_set.hpp> +#include <boost/intrusive/unordered_set.hpp> +#include <boost/static_assert.hpp> +#include "itestvalue.hpp" + +using namespace boost::intrusive; + +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reverse_iterator) +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_reverse_iterator) + +template<bool Value> +struct boolean +{ + static const bool value = Value; +}; + +template<class A, class B> +struct pow2_and_equal_sizes +{ + static const std::size_t a_size = sizeof(A); + static const std::size_t b_size = sizeof(B); + static const bool a_b_sizes_equal = a_size == b_size; + static const bool value = !(a_size & (a_size - 1u)); +}; + +template<class Hook> +struct node : Hook +{}; + +//Avoid testing for uncommon architectures +void test_sizes(boolean<false>, std::size_t) +{} + +template<class C> +void test_iterator_sizes(std::size_t size) +{ + typedef typename C::iterator iterator; + typedef typename C::const_iterator const_iterator; + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT + (::, C, reverse_iterator, iterator) reverse_iterator; + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT + (::, C, const_reverse_iterator, const_iterator) const_reverse_iterator; + + BOOST_TEST_EQ(sizeof(iterator), size); + BOOST_TEST_EQ(sizeof(const_iterator), size); + BOOST_TEST_EQ(sizeof(iterator), sizeof(reverse_iterator)); + BOOST_TEST_EQ(sizeof(const_iterator), size); + BOOST_TEST_EQ(sizeof(const_iterator), sizeof(const_reverse_iterator)); +} + +//Test sizes for common 32 and 64 bit architectures +void test_sizes(boolean<true>, std::size_t wordsize) +{ + { //list + typedef list<node<list_base_hook<> > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes<c>(wordsize); + } + { + typedef list<node<list_base_hook<> >, constant_time_size<false> > c; + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes<c>(wordsize); + } + { + typedef list< node< list_base_hook<> >, header_holder_type< heap_node_holder< list_node<void*>* > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes<c>(wordsize); + } + { + typedef list< node< list_base_hook<> >, constant_time_size<false>, header_holder_type< heap_node_holder< list_node<void*>* > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*1); + test_iterator_sizes<c>(wordsize); + } + { //slist + typedef slist<node< slist_base_hook<> > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes<c>(wordsize); + } + { + typedef slist<node< slist_base_hook<> >, constant_time_size<false> > c; + BOOST_TEST_EQ(sizeof(c), wordsize*1); + test_iterator_sizes<c>(wordsize); + } + { + typedef slist<node< slist_base_hook<> >, cache_last<true> > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes<c>(wordsize); + } + { //set + typedef set<node< set_base_hook<> > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*5); + test_iterator_sizes<c>(wordsize); + } + { + typedef set<node< set_base_hook<> > , constant_time_size<false> > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes<c>(wordsize); + } + { + typedef set<node< set_base_hook<optimize_size<true> > > , constant_time_size<false> > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes<c>(wordsize); + } + { + typedef set< node< set_base_hook<> >, header_holder_type< heap_node_holder< rbtree_node<void*>* > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes<c>(wordsize); + } + { + typedef set< node< set_base_hook<> >, constant_time_size<false>, header_holder_type< heap_node_holder< rbtree_node<void*>* > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*1); + test_iterator_sizes<c>(wordsize); + } + { //avl + typedef avl_set<node< avl_set_base_hook<> > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*5); + test_iterator_sizes<c>(wordsize); + } + { + typedef avl_set<node< avl_set_base_hook<> > , constant_time_size<false> > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes<c>(wordsize); + } + { + typedef avl_set<node< avl_set_base_hook<optimize_size<true> > > , constant_time_size<false> > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes<c>(wordsize); + } + { + typedef avl_set< node< avl_set_base_hook<> >, header_holder_type< heap_node_holder< avltree_node<void*>* > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes<c>(wordsize); + } + { + typedef avl_set< node< avl_set_base_hook<> >, constant_time_size<false>, header_holder_type< heap_node_holder< avltree_node<void*>* > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*1); + test_iterator_sizes<c>(wordsize); + } + { //bs + typedef bs_set<node< bs_set_base_hook<> > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes<c>(wordsize); + } + { + typedef bs_set<node< bs_set_base_hook<> > , constant_time_size<false> > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes<c>(wordsize); + } + { //splay + typedef splay_set<node< bs_set_base_hook<> > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes<c>(wordsize); + } + { + typedef splay_set<node< bs_set_base_hook<> > , constant_time_size<false> > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes<c>(wordsize); + } + { //scapegoat + typedef sg_set<node< bs_set_base_hook<> > > c; + BOOST_TEST_EQ(sizeof(c), (wordsize*5+sizeof(float)*2)); + test_iterator_sizes<c>(wordsize); + } + { //treap + typedef treap_set<node< bs_set_base_hook<> > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes<c>(wordsize); + } + { + typedef treap_set<node< bs_set_base_hook<> > , constant_time_size<false> > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes<c>(wordsize); + } + { //unordered + typedef unordered_set<node< unordered_set_base_hook<> > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes<c>(wordsize*2); + } + { + typedef unordered_set<node< unordered_set_base_hook<> > , power_2_buckets<true> > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes<c>(wordsize*2); + } + { + typedef unordered_set<node< unordered_set_base_hook<> >, constant_time_size<false> > c; + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes<c>(wordsize*2); + } + { + typedef unordered_set<node< unordered_set_base_hook< optimize_multikey<true> > >, constant_time_size<false> > c; + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes<c>(wordsize*2); + } + { + typedef unordered_set<node< unordered_set_base_hook< optimize_multikey<true> > >, incremental<true> > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes<c>(wordsize*2); + } +} + +int main() +{ + test_sizes(boolean< pow2_and_equal_sizes<std::size_t, void*>::value >(), sizeof(std::size_t)); + return ::boost::report_errors(); +} diff --git a/src/boost/libs/intrusive/test/custom_bucket_traits_test.cpp b/src/boost/libs/intrusive/test/custom_bucket_traits_test.cpp new file mode 100644 index 00000000..843cf849 --- /dev/null +++ b/src/boost/libs/intrusive/test/custom_bucket_traits_test.cpp @@ -0,0 +1,129 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2013 +// +// 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 <boost/intrusive/unordered_set.hpp> +#include <boost/intrusive/detail/mpl.hpp> +#include <boost/functional/hash.hpp> +#include <boost/static_assert.hpp> +#include <vector> + +using namespace boost::intrusive; + +class MyClass : public unordered_set_base_hook<> +{ + int int_; + + public: + MyClass(int i = 0) : int_(i) + {} + unordered_set_member_hook<> member_hook_; + + friend bool operator==(const MyClass &l, const MyClass &r) + { return l.int_ == r.int_; } + + friend std::size_t hash_value(const MyClass &v) + { return boost::hash_value(v.int_); } +}; + +struct uset_value_traits +{ + typedef slist_node_traits<void*> node_traits; + typedef node_traits::node_ptr node_ptr; + typedef node_traits::const_node_ptr const_node_ptr; + typedef MyClass value_type; + typedef MyClass * pointer; + typedef const MyClass * const_pointer; + static const link_mode_type link_mode = normal_link; + + static node_ptr to_node_ptr (value_type &value) + { return node_ptr(&value); } + static const_node_ptr to_node_ptr (const value_type &value) + { return const_node_ptr(&value); } + static pointer to_value_ptr(node_ptr n) + { return static_cast<value_type*>(n); } + static const_pointer to_value_ptr(const_node_ptr n) + { return static_cast<const value_type*>(n); } +}; + +//Base +typedef base_hook< unordered_set_base_hook<> > BaseHook; +typedef unordered_bucket<BaseHook>::type BaseBucketType; +typedef unordered_bucket_ptr<BaseHook>::type BaseBucketPtrType; +typedef unordered_set<MyClass, BaseHook> BaseUset; +//Member +typedef member_hook + < MyClass, unordered_set_member_hook<> + , &MyClass::member_hook_ > MemberHook; +typedef unordered_bucket<MemberHook>::type MemberBucketType; +typedef unordered_bucket_ptr<MemberHook>::type MemberBucketPtrType; +typedef unordered_set<MyClass, MemberHook> MemberUset; +//Explicit +typedef value_traits< uset_value_traits > Traits; +typedef unordered_bucket<Traits>::type TraitsBucketType; +typedef unordered_bucket_ptr<Traits>::type TraitsBucketPtrType; +typedef unordered_set<MyClass, Traits> TraitsUset; + +struct uset_bucket_traits +{ + //Power of two bucket length + static const std::size_t NumBuckets = 128; + + uset_bucket_traits(BaseBucketType *buckets) + : buckets_(buckets) + {} + + uset_bucket_traits(const uset_bucket_traits &other) + : buckets_(other.buckets_) + {} + + BaseBucketType * bucket_begin() const + { return buckets_; } + + std::size_t bucket_count() const + { return NumBuckets; } + + BaseBucketType *buckets_; +}; + +typedef unordered_set + <MyClass, bucket_traits<uset_bucket_traits>, power_2_buckets<true> > + BucketTraitsUset; + +int main() +{ + BOOST_STATIC_ASSERT((detail::is_same<BaseUset::bucket_type, BaseBucketType>::value)); + BOOST_STATIC_ASSERT((detail::is_same<MemberUset::bucket_type, MemberBucketType>::value)); + BOOST_STATIC_ASSERT((detail::is_same<TraitsUset::bucket_type, TraitsBucketType>::value)); + BOOST_STATIC_ASSERT((detail::is_same<BaseBucketType, MemberBucketType>::value)); + BOOST_STATIC_ASSERT((detail::is_same<BaseBucketType, TraitsBucketType>::value)); + BOOST_STATIC_ASSERT((detail::is_same<BaseBucketPtrType, TraitsBucketPtrType>::value)); + BOOST_STATIC_ASSERT((detail::is_same<BaseBucketPtrType, MemberBucketPtrType>::value)); + BOOST_STATIC_ASSERT((detail::is_same<BaseBucketPtrType, BaseBucketType*>::value)); + + typedef std::vector<MyClass>::iterator VectIt; + typedef std::vector<MyClass>::reverse_iterator VectRit; + std::vector<MyClass> values; + + for(int i = 0; i < 100; ++i) values.push_back(MyClass(i)); + + BaseBucketType buckets[uset_bucket_traits::NumBuckets]; + uset_bucket_traits btraits(buckets); + BucketTraitsUset uset(btraits); + + for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it) + uset.insert(*it); + + for( VectRit it(values.rbegin()), itend(values.rend()); it != itend; ++it){ + if(uset.find(*it) == uset.cend()) return 1; + } + + return 0; +} diff --git a/src/boost/libs/intrusive/test/default_hook_test.cpp b/src/boost/libs/intrusive/test/default_hook_test.cpp new file mode 100644 index 00000000..a8efa994 --- /dev/null +++ b/src/boost/libs/intrusive/test/default_hook_test.cpp @@ -0,0 +1,166 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2013 +// +// 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 <boost/intrusive/list.hpp> +#include <boost/intrusive/slist.hpp> +#include <boost/intrusive/set.hpp> +#include <boost/intrusive/unordered_set.hpp> +#include <boost/intrusive/splay_set.hpp> +#include <boost/intrusive/avl_set.hpp> +#include <boost/intrusive/sg_set.hpp> +#include <boost/intrusive/treap_set.hpp> +#include <boost/intrusive/bs_set.hpp> +#include <boost/intrusive/pointer_traits.hpp> +#include "smart_ptr.hpp" +#include <vector> + +using namespace boost::intrusive; + +class MyClass + +: public list_base_hook + < void_pointer<smart_ptr<void> >, link_mode<safe_link> > +, public slist_base_hook + < void_pointer<smart_ptr<void> >, link_mode<safe_link> > +, public set_base_hook + < void_pointer<smart_ptr<void> >, link_mode<safe_link> > +, public unordered_set_base_hook + < void_pointer<smart_ptr<void> >, link_mode<safe_link> > +, public avl_set_base_hook + < void_pointer<smart_ptr<void> >, link_mode<safe_link> > +, public bs_set_base_hook + < void_pointer<smart_ptr<void> >, link_mode<safe_link> > +{ + int int_; + + public: + MyClass(int i) + : int_(i) + {} + + friend bool operator<(const MyClass &l, const MyClass &r) + { return l.int_ < r.int_; } + + friend bool operator==(const MyClass &l, const MyClass &r) + { return l.int_ == r.int_; } + + friend std::size_t hash_value(const MyClass &v) + { return boost::hash_value(v.int_); } + + friend bool priority_order(const MyClass &l, const MyClass &r) + { return l.int_ < r.int_; } +}; + +//Define a list that will store MyClass using the public base hook +typedef list<MyClass> List; +typedef slist<MyClass> Slist; +typedef set<MyClass> Set; +typedef unordered_set<MyClass> USet; +typedef avl_set<MyClass> AvlSet; +typedef splay_set<MyClass> SplaySet; +typedef treap_set<MyClass> TreapSet; +typedef sg_set<MyClass> SgSet; +typedef bs_set<MyClass> BsSet; + +int main() +{ + typedef std::vector<MyClass>::iterator VectIt; + typedef std::vector<MyClass>::reverse_iterator VectRit; + + //Create several MyClass objects, each one with a different value + std::vector<MyClass> values; + for(int i = 0; i < 100; ++i) values.push_back(MyClass(i)); + + { + List my_list; + Slist my_slist; + Set my_set; + USet::bucket_type buckets[100]; + USet my_uset(USet::bucket_traits(pointer_traits<USet::bucket_ptr>::pointer_to(*buckets), 100)); + AvlSet my_avlset; + SplaySet my_splayset; + + //Now insert them in the reverse order + //in the base hook intrusive list + for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){ + my_list.push_front(*it); + my_slist.push_front(*it); + my_set.insert(*it); + my_uset.insert(*it); + my_avlset.insert(*it); + my_splayset.insert(*it); + } + + //Now test lists + { + List::const_iterator list_it(my_list.cbegin()); + Slist::const_iterator slist_it(my_slist.cbegin()); + Set::const_reverse_iterator set_rit(my_set.crbegin()); + AvlSet::const_reverse_iterator avl_set_rit(my_avlset.crbegin()); + SplaySet::const_reverse_iterator splay_set_rit(my_splayset.crbegin()); + + VectRit vect_it(values.rbegin()), vect_itend(values.rend()); + + //Test the objects inserted in the base hook list + for(; vect_it != vect_itend + ; ++vect_it, ++list_it + , ++slist_it, ++set_rit + , ++avl_set_rit + , ++splay_set_rit + ){ + if(&*list_it != &*vect_it) return 1; + if(&*slist_it != &*vect_it) return 1; + if(&*set_rit != &*vect_it) return 1; + if(&*avl_set_rit != &*vect_it) return 1; + if(&*splay_set_rit != &*vect_it)return 1; + if(my_uset.find(*set_rit) == my_uset.cend()) return 1; + } + } + } + //Since treap_set, sg_set & bs_set reuse the hook, treat them apart + { + TreapSet my_treapset; + for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){ + my_treapset.insert(*it); + } + + TreapSet::const_reverse_iterator treap_set_rit(my_treapset.crbegin()); + VectRit vect_it(values.rbegin()), vect_itend(values.rend()); + for(; vect_it != vect_itend; ++vect_it, ++treap_set_rit){ + if(&*treap_set_rit != &*vect_it) return 1; + } + } + { + SgSet my_sgset; + for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){ + my_sgset.insert(*it); + } + + SgSet::const_reverse_iterator sg_set_rit(my_sgset.crbegin()); + VectRit vect_it(values.rbegin()), vect_itend(values.rend()); + for(; vect_it != vect_itend; ++vect_it, ++sg_set_rit){ + if(&*sg_set_rit != &*vect_it) return 1; + } + } + { + BsSet my_bsset; + for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){ + my_bsset.insert(*it); + } + + BsSet::const_reverse_iterator bs_set_rit(my_bsset.crbegin()); + VectRit vect_it(values.rbegin()), vect_itend(values.rend()); + for(; vect_it != vect_itend; ++vect_it, ++bs_set_rit){ + if(&*bs_set_rit != &*vect_it) return 1; + } + } + return 0; +} diff --git a/src/boost/libs/intrusive/test/function_hook_test.cpp b/src/boost/libs/intrusive/test/function_hook_test.cpp new file mode 100644 index 00000000..9b16395c --- /dev/null +++ b/src/boost/libs/intrusive/test/function_hook_test.cpp @@ -0,0 +1,150 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2010-2013 +// +// 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 <boost/intrusive/parent_from_member.hpp> +#include <boost/intrusive/list.hpp> +#include <boost/intrusive/slist.hpp> +#include <boost/intrusive/set.hpp> +#include <boost/intrusive/unordered_set.hpp> +#include <boost/functional/hash.hpp> + +using namespace boost::intrusive; + +struct MyClass +{ + MyClass() : order(0) {} + int order; + + //This internal type has two hooks + struct InnerNode : public list_base_hook<>, public slist_base_hook<> + , public set_base_hook<>, public unordered_set_base_hook<> + { + list_member_hook<> listhook; + slist_member_hook<> slisthook; + set_member_hook<> sethook; + unordered_set_member_hook<> usethook; + } inner; + + friend bool operator < (const MyClass &l, const MyClass &r) + { return l.order < r.order; } + friend bool operator == (const MyClass &l, const MyClass &r) + { return l.order == r.order; } + friend std::size_t hash_value(const MyClass &value) + { return std::size_t(value.order); } +}; + +//This functor converts between MyClass and the InnerNode member hook +#define InnerMemberHook(TAG, HOOKTYPE, MEMBERNAME)\ + struct InnerMemberHookFunctor##TAG \ + {\ + typedef HOOKTYPE hook_type;\ + typedef hook_type* hook_ptr;\ + typedef const hook_type* const_hook_ptr;\ + typedef MyClass value_type;\ + typedef value_type* pointer;\ + typedef const value_type* const_pointer;\ + \ + static hook_ptr to_hook_ptr (value_type &value)\ + { return &value.inner.MEMBERNAME; }\ + static const_hook_ptr to_hook_ptr(const value_type &value)\ + { return &value.inner.MEMBERNAME; }\ + static pointer to_value_ptr(hook_ptr n)\ + {\ + return get_parent_from_member<MyClass>\ + (get_parent_from_member<MyClass::InnerNode>(n, &MyClass::InnerNode::MEMBERNAME)\ + ,&MyClass::inner\ + );\ + }\ + static const_pointer to_value_ptr(const_hook_ptr n)\ + {\ + return get_parent_from_member<MyClass>\ + (get_parent_from_member<MyClass::InnerNode>(n, &MyClass::InnerNode::MEMBERNAME)\ + ,&MyClass::inner\ + );\ + }\ + };\ +// + + +//This functor converts between MyClass and the InnerNode base hook +#define InnerBaseHook(TAG, HOOKTYPE)\ + struct InnerBaseHookFunctor##TAG \ + {\ + typedef HOOKTYPE hook_type;\ + typedef hook_type* hook_ptr;\ + typedef const hook_type* const_hook_ptr;\ + typedef MyClass value_type;\ + typedef value_type* pointer;\ + typedef const value_type* const_pointer;\ + \ + static hook_ptr to_hook_ptr (value_type &value)\ + { return &value.inner; }\ + static const_hook_ptr to_hook_ptr(const value_type &value)\ + { return &value.inner; }\ + static pointer to_value_ptr(hook_ptr n)\ + {\ + return get_parent_from_member<MyClass>(static_cast<MyClass::InnerNode*>(n),&MyClass::inner);\ + }\ + static const_pointer to_value_ptr(const_hook_ptr n)\ + {\ + return get_parent_from_member<MyClass>(static_cast<const MyClass::InnerNode*>(n),&MyClass::inner);\ + }\ + };\ +// + +//List +InnerMemberHook(List, list_member_hook<>, listhook) +InnerBaseHook(List, list_base_hook<>) +//Slist +InnerMemberHook(Slist, slist_member_hook<>, slisthook) +InnerBaseHook(Slist, slist_base_hook<>) +//Set +InnerMemberHook(Set, set_member_hook<>, sethook) +InnerBaseHook(Set, set_base_hook<>) +//Unordered Set +InnerMemberHook(USet, unordered_set_member_hook<>, usethook) +InnerBaseHook(USet, unordered_set_base_hook<>) + +//Define containers +typedef list < MyClass, function_hook< InnerMemberHookFunctorList> > CustomListMember; +typedef list < MyClass, function_hook< InnerBaseHookFunctorList > > CustomListBase; +typedef slist< MyClass, function_hook< InnerMemberHookFunctorSlist> > CustomSlistMember; +typedef slist< MyClass, function_hook< InnerBaseHookFunctorSlist > > CustomSlistBase; +typedef set < MyClass, function_hook< InnerMemberHookFunctorSet> > CustomSetMember; +typedef set < MyClass, function_hook< InnerBaseHookFunctorSet > > CustomSetBase; +typedef unordered_set< MyClass, function_hook< InnerMemberHookFunctorUSet> > CustomUSetMember; +typedef unordered_set< MyClass, function_hook< InnerBaseHookFunctorUSet > > CustomUSetBase; + +int main() +{ + MyClass n; + CustomListBase listbase; + CustomListMember listmember; + CustomSlistBase slistbase; + CustomSlistMember slistmember; + CustomSetBase setbase; + CustomSetMember setmember; + CustomUSetBase::bucket_type buckets_uset[1]; + CustomUSetBase usetbase(CustomUSetBase::bucket_traits(buckets_uset, 1)); + CustomUSetBase::bucket_type buckets_umultiset[1]; + CustomUSetMember usetmember(CustomUSetMember::bucket_traits(buckets_umultiset, 1)); + + listbase.insert(listbase.begin(), n); + listmember.insert(listmember.begin(), n); + slistbase.insert(slistbase.begin(), n); + slistmember.insert(slistmember.begin(), n); + setbase.insert(n); + setmember.insert(n); + usetbase.insert(n); + usetmember.insert(n); + + return 0; +} diff --git a/src/boost/libs/intrusive/test/generic_assoc_test.hpp b/src/boost/libs/intrusive/test/generic_assoc_test.hpp new file mode 100644 index 00000000..74b4c5f8 --- /dev/null +++ b/src/boost/libs/intrusive/test/generic_assoc_test.hpp @@ -0,0 +1,372 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2013. +// +// 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 <boost/container/vector.hpp> //vector +#include <boost/intrusive/detail/config_begin.hpp> +#include "common_functors.hpp" +#include <boost/intrusive/options.hpp> +#include <boost/intrusive/detail/mpl.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "test_macros.hpp" +#include "test_container.hpp" + +namespace boost{ +namespace intrusive{ +namespace test{ + +BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(has_splay, splay) + +BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(has_rebalance, rebalance) + +BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(has_insert_before, insert_before) + +BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(is_treap, priority_comp) + +template<class ContainerDefiner> +struct test_generic_assoc +{ + typedef typename ContainerDefiner::value_cont_type value_cont_type; + + static void test_all(value_cont_type&); + static void test_root(value_cont_type&); + static void test_clone(value_cont_type&); + static void test_insert_erase_burst(); + static void test_container_from_end(value_cont_type&, detail::true_type); + static void test_container_from_end(value_cont_type&, detail::false_type) {} + static void test_splay_up(value_cont_type&, detail::true_type); + static void test_splay_up(value_cont_type&, detail::false_type) {} + static void test_splay_down(value_cont_type&, detail::true_type); + static void test_splay_down(value_cont_type&, detail::false_type) {} + static void test_rebalance(value_cont_type&, detail::true_type); + static void test_rebalance(value_cont_type&, detail::false_type) {} + static void test_insert_before(value_cont_type&, detail::true_type); + static void test_insert_before(value_cont_type&, detail::false_type) {} + static void test_container_from_iterator(value_cont_type&, detail::true_type); + static void test_container_from_iterator(value_cont_type&, detail::false_type) {} +}; + +template<class ContainerDefiner> +void test_generic_assoc<ContainerDefiner>:: + test_container_from_iterator(value_cont_type& values, detail::true_type) +{ + typedef typename ContainerDefiner::template container + <>::type assoc_type; + assoc_type testset(values.begin(), values.end()); + typedef typename assoc_type::iterator it_type; + typedef typename assoc_type::const_iterator cit_type; + typedef typename assoc_type::size_type sz_type; + sz_type sz = testset.size(); + for(it_type b(testset.begin()), e(testset.end()); b != e; ++b) + { + assoc_type &s = assoc_type::container_from_iterator(b); + const assoc_type &cs = assoc_type::container_from_iterator(cit_type(b)); + BOOST_TEST(&s == &cs); + BOOST_TEST(&s == &testset); + s.erase(b); + BOOST_TEST(testset.size() == (sz-1)); + s.insert(*b); + BOOST_TEST(testset.size() == sz); + } +} + +template<class ContainerDefiner> +void test_generic_assoc<ContainerDefiner>::test_insert_erase_burst() +{ + //value_cont_type values; + const std::size_t MaxValues = 200; + value_cont_type values(MaxValues); + for(std::size_t i = 0; i != MaxValues; ++i){ + (&values[i])->value_ = i; + } + + typedef typename ContainerDefiner::template container + <>::type assoc_type; + typedef typename assoc_type::iterator iterator; + + { //Ordered insertion + erasure + assoc_type testset (values.begin(), values.begin() + values.size()); + TEST_INTRUSIVE_SEQUENCE_EXPECTED(testset, testset.begin()); + testset.check(); + iterator it(testset.begin()), itend(testset.end()); + for(std::size_t i = 0; it != itend; ++i){ + BOOST_TEST(&*it == &values[i]); + it = testset.erase(it); + testset.check(); + } + BOOST_TEST(testset.empty()); + } + + { //Now random insertions + erasure + assoc_type testset; + typedef typename value_cont_type::iterator vec_iterator; + boost::container::vector<vec_iterator> it_vector; + //Random insertion + for(vec_iterator it(values.begin()), itend(values.end()) + ; it != itend + ; ++it){ + it_vector.push_back(it); + } + for(std::size_t i = 0; i != MaxValues; ++i){ + testset.insert(*it_vector[i]); + testset.check(); + } + TEST_INTRUSIVE_SEQUENCE_EXPECTED(testset, testset.begin()); + //Random erasure + random_shuffle(it_vector.begin(), it_vector.end()); + for(std::size_t i = 0; i != MaxValues; ++i){ + testset.erase(testset.iterator_to(*it_vector[i])); + testset.check(); + } + BOOST_TEST(testset.empty()); + } +} + +template<class ContainerDefiner> +void test_generic_assoc<ContainerDefiner>::test_all(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type assoc_type; + test_root(values); + test_clone(values); + test_container_from_end(values, detail::bool_< assoc_type::has_container_from_iterator >()); + test_splay_up(values, detail::bool_< has_splay< assoc_type >::value >()); + test_splay_down(values, detail::bool_< has_splay< assoc_type >::value >()); + test_rebalance(values, detail::bool_< has_rebalance< assoc_type >::value >()); + test_insert_before(values, detail::bool_< has_insert_before< assoc_type >::value >()); + test_insert_erase_burst(); + test_container_from_iterator(values, detail::bool_< assoc_type::has_container_from_iterator >()); +} + +template<class ContainerDefiner> +void test_generic_assoc<ContainerDefiner>::test_root(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container<>::type assoc_type; + typedef typename assoc_type::iterator iterator; + typedef typename assoc_type::const_iterator const_iterator; + + assoc_type testset1; + const assoc_type &ctestset1 = testset1;; + + BOOST_TEST( testset1.root() == testset1.end()); + BOOST_TEST(ctestset1.root() == ctestset1.cend()); + BOOST_TEST( testset1.croot() == ctestset1.cend()); + + + testset1.insert(values.begin(), values.begin() + values.size()); + + iterator i = testset1.root(); + iterator i2(i); + BOOST_TEST( i.go_parent().go_parent() == i2); + + const_iterator ci = ctestset1.root(); + const_iterator ci2(ci); + BOOST_TEST( ci.go_parent().go_parent() == ci2); + + ci = testset1.croot(); + ci2 = ci; + BOOST_TEST( ci.go_parent().go_parent() == ci2); +} + +template<class ContainerDefiner> +void test_generic_assoc<ContainerDefiner>::test_clone(value_cont_type& values) +{ + { + typedef typename ContainerDefiner::template container + <>::type assoc_type; + typedef typename assoc_type::value_type value_type; + typedef typename assoc_type::size_type size_type; + + assoc_type testset1 (values.begin(), values.begin() + values.size()); + assoc_type testset2; + + + size_type const testset1_oldsize = testset1.size(); + testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>()); + BOOST_TEST (testset1.size() == testset1_oldsize); + BOOST_TEST (testset2 == testset1); + testset2.clear_and_dispose(test::delete_disposer<value_type>()); + BOOST_TEST (testset2.empty()); + + //Now test move clone + testset2.clone_from(boost::move(testset1), test::new_nonconst_cloner<value_type>(), test::delete_disposer<value_type>()); + BOOST_TEST (testset2 == testset1); + testset2.clear_and_dispose(test::delete_disposer<value_type>()); + BOOST_TEST (testset2.empty()); + } +} + +template<class ContainerDefiner> +void test_generic_assoc<ContainerDefiner> + ::test_container_from_end(value_cont_type& values, detail::true_type) +{ + typedef typename ContainerDefiner::template container + <>::type assoc_type; + assoc_type testset (values.begin(), values.begin() + values.size()); + BOOST_TEST (testset == assoc_type::container_from_end_iterator(testset.end())); + BOOST_TEST (testset == assoc_type::container_from_end_iterator(testset.cend())); +} + +template<class ContainerDefiner> +void test_generic_assoc<ContainerDefiner>::test_splay_up +(value_cont_type& values, detail::true_type) +{ + typedef typename ContainerDefiner::template container + <>::type assoc_type; + + typedef typename assoc_type::iterator iterator; + typedef value_cont_type orig_set_t; + std::size_t num_values; + orig_set_t original_testset; + { + assoc_type testset (values.begin(), values.end()); + num_values = testset.size(); + original_testset = value_cont_type(testset.begin(), testset.end()); + } + + for(std::size_t i = 0; i != num_values; ++i){ + assoc_type testset (values.begin(), values.end()); + { + iterator it = testset.begin(); + for(std::size_t j = 0; j != i; ++j, ++it){} + testset.splay_up(it); + } + BOOST_TEST (testset.size() == num_values); + iterator it = testset.begin(); + for( typename orig_set_t::const_iterator origit = original_testset.begin() + , origitend = original_testset.end() + ; origit != origitend + ; ++origit, ++it){ + BOOST_TEST(*origit == *it); + } + } +} + +template<class ContainerDefiner> +void test_generic_assoc<ContainerDefiner>::test_splay_down +(value_cont_type& values, detail::true_type) +{ + typedef typename ContainerDefiner::template container + <>::type assoc_type; + + typedef typename assoc_type::iterator iterator; + typedef value_cont_type orig_set_t; + std::size_t num_values; + orig_set_t original_testset; + { + assoc_type testset (values.begin(), values.end()); + num_values = testset.size(); + original_testset = value_cont_type(testset.begin(), testset.end()); + } + + for(std::size_t i = 0; i != num_values; ++i){ + assoc_type testset (values.begin(), values.end()); + BOOST_TEST(testset.size() == num_values); + { + iterator it = testset.begin(); + for(std::size_t j = 0; j != i; ++j, ++it){} + BOOST_TEST(*it == *testset.splay_down(*it)); + } + BOOST_TEST (testset.size() == num_values); + iterator it = testset.begin(); + for( typename orig_set_t::const_iterator origit = original_testset.begin() + , origitend = original_testset.end() + ; origit != origitend + ; ++origit, ++it){ + BOOST_TEST(*origit == *it); + } + } +} + +template<class ContainerDefiner> +void test_generic_assoc<ContainerDefiner>::test_rebalance +(value_cont_type& values, detail::true_type) +{ + typedef typename ContainerDefiner::template container + <>::type assoc_type; + typedef value_cont_type orig_set_t; + orig_set_t original_testset; + { + assoc_type testset (values.begin(), values.end()); + original_testset.assign(testset.begin(), testset.end()); + } + { + assoc_type testset(values.begin(), values.end()); + testset.rebalance(); + TEST_INTRUSIVE_SEQUENCE_EXPECTED(original_testset, testset.begin()); + } + + { + std::size_t numdata; + { + assoc_type testset(values.begin(), values.end()); + numdata = testset.size(); + } + + for(int i = 0; i != (int)numdata; ++i){ + assoc_type testset(values.begin(), values.end()); + typename assoc_type::iterator it = testset.begin(); + for(int j = 0; j != i; ++j) ++it; + testset.rebalance_subtree(it); + TEST_INTRUSIVE_SEQUENCE_EXPECTED(original_testset, testset.begin()); + } + } +} + +template<class ContainerDefiner> +void test_generic_assoc<ContainerDefiner>::test_insert_before +(value_cont_type& values, detail::true_type) +{ + typedef typename ContainerDefiner::template container + <>::type assoc_type; + { + assoc_type testset; + typedef typename value_cont_type::iterator vec_iterator; + for(vec_iterator it(values.begin()), itend(values.end()) + ; it != itend + ; ++it){ + testset.push_back(*it); + } + BOOST_TEST(testset.size() == values.size()); + TEST_INTRUSIVE_SEQUENCE_EXPECTED(values, testset.begin()); + } + { + assoc_type testset; + typedef typename value_cont_type::iterator vec_iterator; + + for(vec_iterator it(--values.end()); true; --it){ + testset.push_front(*it); + if(it == values.begin()){ + break; + } + } + BOOST_TEST(testset.size() == values.size()); + TEST_INTRUSIVE_SEQUENCE_EXPECTED(values, testset.begin()); + } + { + assoc_type testset; + typedef typename value_cont_type::iterator vec_iterator; + typename assoc_type::iterator it_pos = + testset.insert_before(testset.end(), *values.rbegin()); + testset.insert_before(testset.begin(), *values.begin()); + for(vec_iterator it(++values.begin()), itend(--values.end()) + ; it != itend + ; ++it){ + testset.insert_before(it_pos, *it); + } + BOOST_TEST(testset.size() == values.size()); + TEST_INTRUSIVE_SEQUENCE_EXPECTED(values, testset.begin()); + } +} + +}}} //namespace boost::intrusive::test + +#include <boost/intrusive/detail/config_end.hpp> diff --git a/src/boost/libs/intrusive/test/generic_multiset_test.hpp b/src/boost/libs/intrusive/test/generic_multiset_test.hpp new file mode 100644 index 00000000..2a0ee286 --- /dev/null +++ b/src/boost/libs/intrusive/test/generic_multiset_test.hpp @@ -0,0 +1,322 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2013. +// +// 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 <boost/container/vector.hpp> +#include <boost/intrusive/detail/config_begin.hpp> +#include "common_functors.hpp" +#include <boost/detail/lightweight_test.hpp> +#include <boost/intrusive/options.hpp> +#include <boost/intrusive/detail/iterator.hpp> +#include "test_macros.hpp" +#include "test_container.hpp" +#include "generic_assoc_test.hpp" +#include <typeinfo> + +namespace boost{ +namespace intrusive{ +namespace test{ + +template<class ContainerDefiner> +struct test_generic_multiset +{ + typedef typename ContainerDefiner::value_cont_type value_cont_type; + + static void test_all(); + static void test_sort(value_cont_type&); + static void test_insert(value_cont_type&); + static void test_swap(value_cont_type&); + static void test_merge(value_cont_type&); + static void test_find(value_cont_type&); + static void test_impl(); +}; + +template<class ContainerDefiner> +void test_generic_multiset<ContainerDefiner>::test_all () +{ + static const int random_init[6] = { 3, 2, 4, 1, 5, 2 }; + value_cont_type values (6); + for (int i = 0; i < 6; ++i) + (&values[i])->value_ = random_init[i]; + typedef typename ContainerDefiner::template container + <>::type multiset_type; + { + multiset_type testset(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_associative_container(testset, values); + testset.clear(); + testset.insert(values.begin(), values.end()); + test::test_non_unique_container(testset, values); + } + test_sort(values); + test_insert(values); + test_swap(values); + test_merge(values); + test_find(values); + test_impl(); + test_generic_assoc<ContainerDefiner>::test_all(values); +} + +//test case due to an error in tree implementation: +template<class ContainerDefiner> +void test_generic_multiset<ContainerDefiner>::test_impl() +{ + value_cont_type values (5); + for (int i = 0; i < 5; ++i) + (&values[i])->value_ = i; + typedef typename ContainerDefiner::template container + <>::type multiset_type; + + multiset_type testset; + 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<class ContainerDefiner> +void test_generic_multiset<ContainerDefiner>::test_sort(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type multiset_type; + + multiset_type testset1 (values.begin(), values.end()); + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } + + testset1.clear(); + BOOST_TEST (testset1.empty()); + + typedef typename ContainerDefiner::template container + <compare<even_odd> + >::type multiset_type2; + + multiset_type2 testset2 (values.begin(), values.begin() + 6); + { int init_values [] = { 5, 3, 1, 4, 2, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset2.rbegin() ); } + + BOOST_TEST (testset2.begin()->value_ == 2); + BOOST_TEST (testset2.rbegin()->value_ == 5); +} + +//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to: +template<class ContainerDefiner> +void test_generic_multiset<ContainerDefiner>::test_insert(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type multiset_type; + + multiset_type testset; + testset.insert(values.begin() + 2, values.begin() + 5); + testset.check(); + { int init_values [] = { 1, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); } + + typename multiset_type::iterator i = testset.begin(); + BOOST_TEST (i->value_ == 1); + + i = testset.insert (i, values[0]); + testset.check(); + BOOST_TEST (&*i == &values[0]); + + { int init_values [] = { 5, 4, 3, 1 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset.rbegin() ); } + + i = testset.iterator_to (values[2]); + BOOST_TEST (&*i == &values[2]); + + i = multiset_type::s_iterator_to (values[2]); + BOOST_TEST (&*i == &values[2]); + + testset.erase(i); + testset.check(); + + { int init_values [] = { 1, 3, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); } +} + +//test: insert (seq-version), swap, erase (seq-version), size: +template<class ContainerDefiner> +void test_generic_multiset<ContainerDefiner>::test_swap(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type multiset_type; + multiset_type testset1 (values.begin(), values.begin() + 2); + multiset_type testset2; + testset2.insert (values.begin() + 2, values.begin() + 6); + testset1.swap (testset2); + + { int init_values [] = { 1, 2, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } + { int init_values [] = { 2, 3 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); } + + testset1.erase (testset1.iterator_to(values[5]), testset1.end()); + BOOST_TEST (testset1.size() == 1); + BOOST_TEST (&*testset1.begin() == &values[3]); +} + +template<class ContainerDefiner> +void test_generic_multiset<ContainerDefiner>::test_merge(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type multiset_type; + typedef typename multiset_type::key_of_value key_of_value; + typedef typename multiset_type::key_type key_type; + + typedef typename ContainerDefiner::template container + < compare< std::greater<key_type> > >::type multiset_greater_type; + + //original vector: 3, 2, 4, 1, 5, 2 + //2,3 + multiset_type testset1 (values.begin(), values.begin() + 2); + //5, 4, 2, 1 + multiset_greater_type testset2; + testset2.insert (values.begin() + 2, values.begin() + 6); + + testset2.merge(testset1); + testset1.check(); + testset2.check(); + + BOOST_TEST (testset1.empty()); + BOOST_TEST (testset2.size() == 6); + { int init_values [] = { 5, 4, 3, 2, 2, 1 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); } + + value_cont_type cmp_val_cont(1); + typename value_cont_type::reference cmp_val = cmp_val_cont.front(); + (&cmp_val)->value_ = 2; + + BOOST_TEST (*testset2.find(key_of_value()(cmp_val)) == values[5]); + BOOST_TEST (*testset2.find(2, any_greater()) == values[5]); + BOOST_TEST (&*(++testset2.find(key_of_value()(cmp_val))) == &values[1]); + + testset1.merge(testset2); + testset1.check(); + testset2.check(); + + BOOST_TEST (testset1.size() == 6); + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } + BOOST_TEST (*testset1.find(key_of_value()(cmp_val)) == values[5]); + BOOST_TEST (*testset1.find(2, any_less()) == values[5]); + BOOST_TEST (&*(++testset1.find(key_of_value()(cmp_val))) == &values[1]); + BOOST_TEST (testset2.empty()); +} + +//test: find, equal_range (lower_bound, upper_bound): +template<class ContainerDefiner> +void test_generic_multiset<ContainerDefiner>::test_find(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type multiset_type; + typedef typename multiset_type::key_of_value key_of_value; + multiset_type testset (values.begin(), values.end()); + typedef typename multiset_type::iterator iterator; + typedef typename multiset_type::const_iterator const_iterator; + + { + value_cont_type cmp_val_cont(1); + typename value_cont_type::reference cmp_val = cmp_val_cont.front(); + (&cmp_val)->value_ = 2; + iterator i = testset.find (key_of_value()(cmp_val)); + BOOST_TEST (i == testset.find (2, any_less())); + BOOST_TEST (i->value_ == 2); + BOOST_TEST ((++i)->value_ == 2); + std::pair<iterator,iterator> range = testset.equal_range (key_of_value()(cmp_val)); + BOOST_TEST(range == testset.equal_range (2, any_less())); + + BOOST_TEST (range.first->value_ == 2); + BOOST_TEST (range.second->value_ == 3); + BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 2); + + (&cmp_val)->value_ = 7; + BOOST_TEST (testset.find(key_of_value()(cmp_val)) == testset.end()); + BOOST_TEST (testset.find (7, any_less()) == testset.end()); + } + { //1, 2, 2, 3, 4, 5 + const multiset_type &const_testset = testset; + std::pair<iterator,iterator> range; + std::pair<const_iterator, const_iterator> const_range; + value_cont_type cmp_val_cont(2); + typename value_cont_type::reference cmp_val_lower = cmp_val_cont.front(); + typename value_cont_type::reference cmp_val_upper = cmp_val_cont.back(); + { + (&cmp_val_lower)->value_ = 1; + (&cmp_val_upper)->value_ = 2; + //left-closed, right-closed + range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, true); + BOOST_TEST (range == testset.bounded_range (1, 2, any_less(), true, true)); + BOOST_TEST (range.first->value_ == 1); + BOOST_TEST (range.second->value_ == 3); + BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 3); + } + { + (&cmp_val_lower)->value_ = 1; + (&cmp_val_upper)->value_ = 2; + const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false); + BOOST_TEST (const_range == const_testset.bounded_range (1, 2, any_less(), true, false)); + BOOST_TEST (const_range.first->value_ == 1); + BOOST_TEST (const_range.second->value_ == 2); + BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1); + + (&cmp_val_lower)->value_ = 1; + (&cmp_val_upper)->value_ = 3; + range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false); + BOOST_TEST (range == testset.bounded_range (1, 3, any_less(), true, false)); + BOOST_TEST (range.first->value_ == 1); + BOOST_TEST (range.second->value_ == 3); + BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 3); + } + { + (&cmp_val_lower)->value_ = 1; + (&cmp_val_upper)->value_ = 2; + const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), false, true); + BOOST_TEST (const_range == const_testset.bounded_range (1, 2, any_less(), false, true)); + BOOST_TEST (const_range.first->value_ == 2); + BOOST_TEST (const_range.second->value_ == 3); + BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 2); + } + { + (&cmp_val_lower)->value_ = 1; + (&cmp_val_upper)->value_ = 2; + range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), false, false); + BOOST_TEST (range == testset.bounded_range (1, 2, any_less(), false, false)); + BOOST_TEST (range.first->value_ == 2); + BOOST_TEST (range.second->value_ == 2); + BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 0); + } + { + (&cmp_val_lower)->value_ = 5; + (&cmp_val_upper)->value_ = 6; + const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false); + BOOST_TEST (const_range == const_testset.bounded_range (5, 6, any_less(), true, false)); + BOOST_TEST (const_range.first->value_ == 5); + BOOST_TEST (const_range.second == const_testset.end()); + BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1); + } + } +} + +}}} //namespace boost::intrusive::test + +#include <boost/intrusive/detail/config_end.hpp> diff --git a/src/boost/libs/intrusive/test/generic_set_test.hpp b/src/boost/libs/intrusive/test/generic_set_test.hpp new file mode 100644 index 00000000..92360194 --- /dev/null +++ b/src/boost/libs/intrusive/test/generic_set_test.hpp @@ -0,0 +1,405 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2013. +// +// 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 <boost/container/vector.hpp> +#include <boost/intrusive/detail/config_begin.hpp> +#include "common_functors.hpp" +#include <boost/detail/lightweight_test.hpp> +#include <boost/intrusive/options.hpp> +#include <boost/intrusive/detail/iterator.hpp> +#include <boost/intrusive/detail/mpl.hpp> +#include "test_macros.hpp" +#include "test_container.hpp" +#include "generic_assoc_test.hpp" +#include <typeinfo> +#include <boost/intrusive/priority_compare.hpp> + +namespace boost{ +namespace intrusive{ +namespace test{ + +template<class ContainerDefiner> +struct test_generic_set +{ + static void test_all(); + private: + typedef typename ContainerDefiner::value_cont_type value_cont_type; + static void test_sort(value_cont_type&); + static void test_insert(value_cont_type&); + static void test_insert_advanced(value_cont_type&, detail::true_type); + static void test_insert_advanced(value_cont_type&, detail::false_type); + static void test_swap(value_cont_type&); + static void test_merge(value_cont_type&); + static void test_find(value_cont_type&); + static void test_impl(); +}; + + +template<class ContainerDefiner> +void test_generic_set<ContainerDefiner>::test_all() +{ + typedef typename ContainerDefiner::template container + <>::type set_type; + { + static const int random_init[6] = { 3, 2, 4, 1, 5, 2 }; + value_cont_type values(6); + for (int i = 0; i < 6; ++i) + (&values[i])->value_ = random_init[i]; + + { + set_type testset(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_associative_container(testset, values); + testset.clear(); + testset.insert(values.begin(), values.end()); + test::test_unique_container(testset, values); + } + + test_sort(values); + test_insert(values); + test_insert_advanced(values, detail::bool_< is_treap< set_type >::value >()); + test_swap(values); + test_merge(values); + test_find(values); + test_impl(); + test_generic_assoc<ContainerDefiner>::test_all(values); + } + { + value_cont_type values(6); + for (int i = 0; i < 6; ++i) + (&values[i])->value_ = i+1; + set_type testset(values.begin(), values.end()); + test::test_iterator_bidirectional(testset); + } +} + +//test case due to an error in tree implementation: +template<class ContainerDefiner> +void test_generic_set<ContainerDefiner>::test_impl() +{ + value_cont_type values (5); + for (int i = 0; i < 5; ++i) + (&values[i])->value_ = i; + + typedef typename ContainerDefiner::template container + <>::type set_type; + set_type testset; + 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<class ContainerDefiner> +void test_generic_set<ContainerDefiner>::test_sort(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type set_type; + + set_type testset1 (values.begin(), values.end()); + { int init_values [] = { 1, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } + + testset1.clear(); + BOOST_TEST (testset1.empty()); + + typedef typename ContainerDefiner::template container + < compare<even_odd> >::type set_type2; + + set_type2 testset2 (values.begin(), values.begin() + 6); + { int init_values [] = { 5, 3, 1, 4, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset2.rbegin() ); } + BOOST_TEST (testset2.begin()->value_ == 2); + BOOST_TEST (testset2.rbegin()->value_ == 5); +} + +//test: insert, const_iterator, const_reverse_iterator, erase, s_iterator_to: +template<class ContainerDefiner> +void test_generic_set<ContainerDefiner>::test_insert(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type set_type; + { + set_type testset; + testset.insert(values.begin() + 2, values.begin() + 5); + testset.check(); + + const set_type& const_testset = testset; + { int init_values [] = { 1, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); } + + typename set_type::iterator i = testset.begin(); + BOOST_TEST (i->value_ == 1); + + i = testset.insert (i, values[0]); + testset.check(); + BOOST_TEST (&*i == &values[0]); + + { int init_values [] = { 5, 4, 3, 1 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset.rbegin() ); } + + i = testset.iterator_to (values[2]); + BOOST_TEST (&*i == &values[2]); + + i = set_type::s_iterator_to(values[2]); + BOOST_TEST (&*i == &values[2]); + + typedef typename value_cont_type::const_reference const_reference; + typename set_type::const_iterator ic; + ic = testset.iterator_to (static_cast< const_reference >(values[2])); + BOOST_TEST (&*ic == &values[2]); + ic = set_type::s_iterator_to (static_cast< const_reference >(values[2])); + BOOST_TEST (&*ic == &values[2]); + + testset.erase (i); + testset.check(); + { int init_values [] = { 1, 3, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); } + } +} + +// treap version +template<class ValueType, class KeyType> +struct prio_comp + : priority_compare<int> +{ + bool operator()(const ValueType &v, const KeyType &k) const + { return this->priority_compare<int>::operator()(v.int_value(), k.int_value()); } + + bool operator()(const KeyType &k, const ValueType &v) const + { return this->priority_compare<int>::operator()(k.int_value(), v.int_value()); } +}; + +template<class ContainerDefiner> +void test_generic_set<ContainerDefiner>::test_insert_advanced +(value_cont_type& values, detail::true_type) +{ + typedef typename ContainerDefiner::template container + <>::type set_type; + typedef typename set_type::key_of_value key_of_value; + typedef typename set_type::priority_of_value priority_of_value; + typedef typename set_type::value_type value_type; + typedef priority_compare<> prio_comp_t; + { + set_type testset; + testset.insert(values.begin(), values.begin() + values.size()); + testset.check(); + value_type v(1); + typename set_type::insert_commit_data data; + BOOST_TEST ((!testset.insert_check(1, any_less(), 1, prio_comp_t(), data).second)); + BOOST_TEST ((!testset.insert_check(testset.begin(), 1, any_less(), 1, prio_comp_t(), data).second)); + BOOST_TEST ((!testset.insert_check(key_of_value()(v), priority_of_value()(v), data).second)); + BOOST_TEST ((!testset.insert_check(testset.begin(), key_of_value()(v), priority_of_value()(v), data).second)); + } +} + +//test: insert, const_iterator, const_reverse_iterator, erase, s_iterator_to: +template<class ContainerDefiner> +void test_generic_set<ContainerDefiner>::test_insert_advanced +(value_cont_type& values, detail::false_type) +{ + typedef typename ContainerDefiner::template container + <>::type set_type; + typedef typename set_type::key_of_value key_of_value; + typedef typename set_type::value_type value_type; + { + set_type testset; + testset.insert(values.begin(), values.begin() + values.size()); + testset.check(); + value_type v(1); + typename set_type::insert_commit_data data; + BOOST_TEST ((!testset.insert_check(1, any_less(), data).second)); + BOOST_TEST ((!testset.insert_check(key_of_value()(v), data).second)); + BOOST_TEST ((!testset.insert_check(testset.begin(), 1, any_less(), data).second)); + BOOST_TEST ((!testset.insert_check(testset.begin(), key_of_value()(v), data).second)); + } +} + +//test: insert (seq-version), swap, erase (seq-version), size: +template<class ContainerDefiner> +void test_generic_set<ContainerDefiner>::test_swap(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type set_type; + set_type testset1 (values.begin(), values.begin() + 2); + set_type testset2; + testset2.insert (values.begin() + 2, values.begin() + 6); + testset1.swap (testset2); + + { int init_values [] = { 1, 2, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } + + { int init_values [] = { 2, 3 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); } + + 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]); +} + +template<class ContainerDefiner> +void test_generic_set<ContainerDefiner>::test_merge(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type set_type; + typedef typename set_type::key_type key_type; + + typedef typename ContainerDefiner::template container + < compare< std::greater<key_type> > >::type set_greater_type; + + //2,3 + set_type testset1 (values.begin(), values.begin() + 2); + //5, 4, 2, 1 + set_greater_type testset2; + testset2.insert (values.begin() + 2, values.begin() + 6); + + testset2.merge(testset1); + testset1.check(); + testset2.check(); + + BOOST_TEST (testset1.size() == 1); + { int init_values [] = { 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } + BOOST_TEST (&*testset1.begin() == &values[1]); + + BOOST_TEST (testset2.size() == 5); + { int init_values [] = { 5, 4, 3, 2, 1 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); } + + testset1.merge(testset2); + testset1.check(); + testset2.check(); + + BOOST_TEST (testset1.size() == 5); + { int init_values [] = { 1, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } + + BOOST_TEST (testset2.size() == 1); + { int init_values [] = { 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); } + BOOST_TEST (&*testset2.begin() == &values[5]); +} + +//test: find, equal_range (lower_bound, upper_bound), bounded_range: +template<class ContainerDefiner> +void test_generic_set<ContainerDefiner>::test_find(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type set_type; + set_type testset (values.begin(), values.end()); + typedef typename set_type::iterator iterator; + typedef typename set_type::const_iterator const_iterator; + typedef typename set_type::key_of_value key_of_value; + typedef typename value_cont_type::reference reference; + + { + //value_type cmp_val; + value_cont_type cmp_val_cont(1); + reference cmp_val = cmp_val_cont.front(); + (&cmp_val)->value_ = 2; + iterator i = testset.find(key_of_value()(cmp_val)); + BOOST_TEST (i == testset.find(2, any_less())); + BOOST_TEST (i->value_ == 2); + BOOST_TEST ((++i)->value_ != 2); + + std::pair<iterator,iterator> range = testset.equal_range (key_of_value()(cmp_val)); + BOOST_TEST(range == testset.equal_range (2, any_less())); + + BOOST_TEST (range.first->value_ == 2); + BOOST_TEST (range.second->value_ == 3); + BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 1); + + (&cmp_val)->value_ = 7; + BOOST_TEST (testset.find (key_of_value()(cmp_val)) == testset.end()); + BOOST_TEST (testset.find (7, any_less()) == testset.end()); + } + + { + const set_type &const_testset = testset; + std::pair<iterator,iterator> range; + std::pair<const_iterator, const_iterator> const_range; + //value_type cmp_val_lower, cmp_val_upper; + value_cont_type cmp_val_cont(2); + reference cmp_val_lower = cmp_val_cont.front(); + reference cmp_val_upper = cmp_val_cont.back(); + { + (&cmp_val_lower)->value_ = 1; + (&cmp_val_upper)->value_ = 2; + //left-closed, right-closed + range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, true); + BOOST_TEST (range == testset.bounded_range (1, 2, any_less(), true, true)); + BOOST_TEST (range.first->value_ == 1); + BOOST_TEST (range.second->value_ == 3); + BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 2); + } + { + (&cmp_val_lower)->value_ = 1; + (&cmp_val_upper)->value_ = 2; + const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false); + BOOST_TEST (const_range == const_testset.bounded_range (1, 2, any_less(), true, false)); + BOOST_TEST (const_range.first->value_ == 1); + BOOST_TEST (const_range.second->value_ == 2); + BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1); + + (&cmp_val_lower)->value_ = 1; + (&cmp_val_upper)->value_ = 3; + range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false); + BOOST_TEST (range == testset.bounded_range (1, 3, any_less(), true, false)); + BOOST_TEST (range.first->value_ == 1); + BOOST_TEST (range.second->value_ == 3); + BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 2); + } + { + (&cmp_val_lower)->value_ = 1; + (&cmp_val_upper)->value_ = 2; + const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), false, true); + BOOST_TEST (const_range == const_testset.bounded_range (1, 2, any_less(), false, true)); + BOOST_TEST (const_range.first->value_ == 2); + BOOST_TEST (const_range.second->value_ == 3); + BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1); + } + { + (&cmp_val_lower)->value_ = 1; + (&cmp_val_upper)->value_ = 2; + range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), false, false); + BOOST_TEST (range == testset.bounded_range (1, 2, any_less(), false, false)); + BOOST_TEST (range.first->value_ == 2); + BOOST_TEST (range.second->value_ == 2); + BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 0); + } + { + (&cmp_val_lower)->value_ = 5; + (&cmp_val_upper)->value_ = 6; + const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false); + BOOST_TEST (const_range == const_testset.bounded_range (5, 6, any_less(), true, false)); + BOOST_TEST (const_range.first->value_ == 5); + BOOST_TEST (const_range.second == const_testset.end()); + BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1); + } + } +} + +}}} //namespace boost::intrusive::test + +#include <boost/intrusive/detail/config_end.hpp> diff --git a/src/boost/libs/intrusive/test/has_member_function_callable_with.cpp b/src/boost/libs/intrusive/test/has_member_function_callable_with.cpp new file mode 100644 index 00000000..41242a8b --- /dev/null +++ b/src/boost/libs/intrusive/test/has_member_function_callable_with.cpp @@ -0,0 +1,234 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2014. 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. +// +////////////////////////////////////////////////////////////////////////////// +//User define +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME func0to3 +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0 +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 3 +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace func0to3ns { +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END } +#include <boost/intrusive/detail/has_member_function_callable_with.hpp> + +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME func1to2 +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1 +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 2 +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace func1to2ns { +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END } +#include <boost/intrusive/detail/has_member_function_callable_with.hpp> + +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME func3to3 +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 3 +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 3 +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace func3to3ns { +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END } +#include <boost/intrusive/detail/has_member_function_callable_with.hpp> + +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME func0to0 +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0 +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0 +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace func0to0ns { +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END } +#include <boost/intrusive/detail/has_member_function_callable_with.hpp> + +/////////////////// +/////////////////// +// TEST CODE +/////////////////// +/////////////////// + +struct functor +{ + //func0to3 + void func0to3(); + void func0to3(const int&); + void func0to3(const int&, const int&); + void func0to3(const int&, const int&, const int&); + //func1to2 + void func1to2(const int&); + void func1to2(const int&, const int&); + //func3to3 + void func3to3(const int&, const int&, const int&); + //func0to0 + void func0to0(); +}; + +struct functor2 +{ + void func0to3(char*); + void func0to3(int, char*); + void func0to3(int, char*, double); + void func0to3(const int&, char*, void *); + //func1to2 + void func1to2(char*); + void func1to2(int, char*); + void func1to2(int, char*, double); + //func3to3 + void func3to3(const int&, char*, void *); +}; + +struct functor3 +{ + +}; + +struct functor4 +{ + //func0to3 + void func0to3(...); + template<class T> void func0to3(int, const T &); + template<class T> void func0to3(const T &); + template<class T, class U> void func0to3(int, const T &, const U &); + //func1to2 + template<class T> void func1to2(int, const T &); + template<class T> void func1to2(const T &); + template<class T, class U> void func1to2(int, const T &, const U &); + //func3to3 + void func3to3(...); + template<class T, class U> void func3to3(int, const T &, const U &); +}; + +int main() +{ + #if !defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED) + { //func0to3 0 arg + using func0to3ns::has_member_function_callable_with_func0to3; + int check1[ has_member_function_callable_with_func0to3<functor>::value ? 1 : -1]; + int check2[!has_member_function_callable_with_func0to3<functor2>::value ? 1 : -1]; + int check3[!has_member_function_callable_with_func0to3<functor3>::value ? 1 : -1]; + int check4[ has_member_function_callable_with_func0to3<functor4>::value ? 1 : -1]; + (void)check1; + (void)check2; + (void)check3; + (void)check4; + } + { //func0to0 0 arg + using func0to0ns::has_member_function_callable_with_func0to0; + int check1[ has_member_function_callable_with_func0to0<functor>::value ? 1 : -1]; + int check2[!has_member_function_callable_with_func0to0<functor2>::value ? 1 : -1]; + int check3[!has_member_function_callable_with_func0to0<functor3>::value ? 1 : -1]; + (void)check1; + (void)check2; + (void)check3; + } + #endif + + { //func0to3 1arg + using func0to3ns::has_member_function_callable_with_func0to3; + int check1[ has_member_function_callable_with_func0to3<functor, int>::value ? 1 : -1]; + int check2[!has_member_function_callable_with_func0to3<functor, char*>::value ? 1 : -1]; + int check3[!has_member_function_callable_with_func0to3<functor2, int>::value ? 1 : -1]; + int check4[ has_member_function_callable_with_func0to3<functor2, char*>::value ? 1 : -1]; + int check5[!has_member_function_callable_with_func0to3<functor3, int>::value ? 1 : -1]; + int check6[!has_member_function_callable_with_func0to3<functor3, char*>::value ? 1 : -1]; + int check7[ has_member_function_callable_with_func0to3<functor4, int>::value ? 1 : -1]; + int check8[ has_member_function_callable_with_func0to3<functor4, char*>::value ? 1 : -1]; + (void)check1; + (void)check2; + (void)check3; + (void)check4; + (void)check5; + (void)check6; + (void)check7; + (void)check8; + } + + { //func1to2 1arg + using func1to2ns::has_member_function_callable_with_func1to2; + int check1[ has_member_function_callable_with_func1to2<functor, int>::value ? 1 : -1]; + int check2[!has_member_function_callable_with_func1to2<functor, char*>::value ? 1 : -1]; + int check3[!has_member_function_callable_with_func1to2<functor2, int>::value ? 1 : -1]; + int check4[ has_member_function_callable_with_func1to2<functor2, char*>::value ? 1 : -1]; + int check5[!has_member_function_callable_with_func1to2<functor3, int>::value ? 1 : -1]; + int check6[!has_member_function_callable_with_func1to2<functor3, char*>::value ? 1 : -1]; + int check7[ has_member_function_callable_with_func1to2<functor4, int>::value ? 1 : -1]; + int check8[ has_member_function_callable_with_func1to2<functor4, char*>::value ? 1 : -1]; + (void)check1; + (void)check2; + (void)check3; + (void)check4; + (void)check5; + (void)check6; + (void)check7; + (void)check8; + } + + { //func0to3 2arg + using func0to3ns::has_member_function_callable_with_func0to3; + int check1[ has_member_function_callable_with_func0to3<functor, int, int>::value ? 1 : -1]; + int check2[!has_member_function_callable_with_func0to3<functor, int, char*>::value ? 1 : -1]; + int check3[!has_member_function_callable_with_func0to3<functor2, int, int>::value ? 1 : -1]; + int check4[ has_member_function_callable_with_func0to3<functor2, int, char*>::value ? 1 : -1]; + int check5[!has_member_function_callable_with_func0to3<functor3, int, int>::value ? 1 : -1]; + int check6[!has_member_function_callable_with_func0to3<functor3, int, char*>::value ? 1 : -1]; + int check7[ has_member_function_callable_with_func0to3<functor4, int, char*>::value ? 1 : -1]; + (void)check1; + (void)check2; + (void)check3; + (void)check4; + (void)check5; + (void)check6; + (void)check7; + } + + { //func1to2 2arg + using func1to2ns::has_member_function_callable_with_func1to2; + int check1[ has_member_function_callable_with_func1to2<functor, int, int>::value ? 1 : -1]; + int check2[!has_member_function_callable_with_func1to2<functor, int, char*>::value ? 1 : -1]; + int check3[!has_member_function_callable_with_func1to2<functor2, int, int>::value ? 1 : -1]; + int check4[ has_member_function_callable_with_func1to2<functor2, int, char*>::value ? 1 : -1]; + int check5[!has_member_function_callable_with_func1to2<functor3, int, int>::value ? 1 : -1]; + int check6[!has_member_function_callable_with_func1to2<functor3, int, char*>::value ? 1 : -1]; + int check7[ has_member_function_callable_with_func1to2<functor4, int, char*>::value ? 1 : -1]; + (void)check1; + (void)check2; + (void)check3; + (void)check4; + (void)check5; + (void)check6; + (void)check7; + } + + { //func0to3 3arg + using func0to3ns::has_member_function_callable_with_func0to3; + int check1[ has_member_function_callable_with_func0to3<functor, int, int, int>::value ? 1 : -1]; + int check2[!has_member_function_callable_with_func0to3<functor, int, char*, int>::value ? 1 : -1]; + int check3[!has_member_function_callable_with_func0to3<functor2, int, int, int>::value ? 1 : -1]; + int check4[ has_member_function_callable_with_func0to3<functor2, int, char*, void*>::value ? 1 : -1]; + int check5[!has_member_function_callable_with_func0to3<functor3, int, int, int>::value ? 1 : -1]; + int check6[!has_member_function_callable_with_func0to3<functor3, int, char*, void*>::value ? 1 : -1]; + int check7[ has_member_function_callable_with_func0to3<functor4, int, char*, int>::value ? 1 : -1]; + (void)check1; + (void)check2; + (void)check3; + (void)check4; + (void)check5; + (void)check6; + (void)check7; + } + + { //func3to3 3arg + using func3to3ns::has_member_function_callable_with_func3to3; + int check1[ has_member_function_callable_with_func3to3<functor, int, int, int>::value ? 1 : -1]; + int check2[!has_member_function_callable_with_func3to3<functor, int, char*, int>::value ? 1 : -1]; + int check3[!has_member_function_callable_with_func3to3<functor2, int, int, int>::value ? 1 : -1]; + int check4[ has_member_function_callable_with_func3to3<functor2, int, char*, void*>::value ? 1 : -1]; + int check5[!has_member_function_callable_with_func3to3<functor3, int, int, int>::value ? 1 : -1]; + int check6[!has_member_function_callable_with_func3to3<functor3, int, char*, void*>::value ? 1 : -1]; + int check7[ has_member_function_callable_with_func3to3<functor4, int, char*, int>::value ? 1 : -1]; + (void)check1; + (void)check2; + (void)check3; + (void)check4; + (void)check5; + (void)check6; + (void)check7; + } + + return 0; +} diff --git a/src/boost/libs/intrusive/test/has_member_function_callable_with_no_decltype.cpp b/src/boost/libs/intrusive/test/has_member_function_callable_with_no_decltype.cpp new file mode 100644 index 00000000..98037ba1 --- /dev/null +++ b/src/boost/libs/intrusive/test/has_member_function_callable_with_no_decltype.cpp @@ -0,0 +1,12 @@ +#include <boost/config.hpp> + +#ifndef BOOST_NO_CXX11_DECLTYPE +# define BOOST_NO_CXX11_DECLTYPE +# include "has_member_function_callable_with.cpp" +#else + int main() + { + return 0; + } +#endif + diff --git a/src/boost/libs/intrusive/test/has_member_function_callable_with_no_variadic.cpp b/src/boost/libs/intrusive/test/has_member_function_callable_with_no_variadic.cpp new file mode 100644 index 00000000..1be78322 --- /dev/null +++ b/src/boost/libs/intrusive/test/has_member_function_callable_with_no_variadic.cpp @@ -0,0 +1,12 @@ +#include <boost/config.hpp> + +#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES +# define BOOST_NO_CXX11_VARIADIC_TEMPLATES +# include "has_member_function_callable_with.cpp" +#else + int main() + { + return 0; + } +#endif + diff --git a/src/boost/libs/intrusive/test/int_holder.hpp b/src/boost/libs/intrusive/test/int_holder.hpp new file mode 100644 index 00000000..785a3672 --- /dev/null +++ b/src/boost/libs/intrusive/test/int_holder.hpp @@ -0,0 +1,117 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (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 + +#include <boost/functional/hash/hash.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<int> hasher; + return hasher((&t)->int_value()); + } + + int int_; +}; + +template<class ValueType> +struct int_holder_key_of_value +{ + typedef int_holder type; + + type operator()(const ValueType &tv) const + { return tv.get_int_holder(); } +}; + +template<class ValueType> +struct int_priority_of_value +{ + typedef int type; + + type operator()(const ValueType &tv) const + { return tv.int_value(); } +}; + +} //namespace boost{ +} //namespace intrusive{ + +#endif //BOOST_INTRUSIVE_DETAIL_INT_HOLDER_HPP diff --git a/src/boost/libs/intrusive/test/iterator_test.hpp b/src/boost/libs/intrusive/test/iterator_test.hpp new file mode 100644 index 00000000..486cdd81 --- /dev/null +++ b/src/boost/libs/intrusive/test/iterator_test.hpp @@ -0,0 +1,375 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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 <boost/intrusive/detail/iterator.hpp> +#include <boost/intrusive/detail/mpl.hpp> +#include <boost/static_assert.hpp> + +namespace boost{ namespace intrusive { namespace test{ + +////////////////////////////////////////////// +// +// Some traits to avoid special cases with +// containers without bidirectional iterators +// +////////////////////////////////////////////// +template<class C> +struct has_member_reverse_iterator +{ + typedef char yes_type; + struct no_type{ char _[2]; }; + + template<typename D> static no_type test(...); + template<typename D> static yes_type test(typename D::reverse_iterator const*); + static const bool value = sizeof(test<C>(0)) == sizeof(yes_type); +}; + +template<class C> +struct has_member_const_reverse_iterator +{ + typedef char yes_type; + struct no_type{ char _[2]; }; + + template<typename D> static no_type test(...); + template<typename D> static yes_type test(typename D::const_reverse_iterator const*); + static const bool value = sizeof(test<C>(0)) == sizeof(yes_type); +}; + +template<class C, bool = has_member_reverse_iterator<C>::value> +struct get_reverse_iterator +{ + typedef typename C::reverse_iterator type; + static type begin(C &c) { return c.rbegin(); } + static type end(C &c) { return c.rend(); } +}; + +template<class C> +struct get_reverse_iterator<C, false> +{ + typedef typename C::iterator type; + static type begin(C &c) { return c.begin(); } + static type end(C &c) { return c.end(); } +}; + +template<class C, bool = has_member_const_reverse_iterator<C>::value> +struct get_const_reverse_iterator +{ + typedef typename C::const_reverse_iterator type; + static type begin(C &c) { return c.crbegin(); } + static type end(C &c) { return c.crend(); } +}; + +template<class C> +struct get_const_reverse_iterator<C, false> +{ + typedef typename C::const_iterator type; + static type begin(C &c) { return c.cbegin(); } + static type end(C &c) { return c.cend(); } +}; + +////////////////////////////////////////////// +// +// Iterator tests +// +////////////////////////////////////////////// + +template<class I> +void test_iterator_operations(I b, I e) +{ + //Test the range is not empty + BOOST_TEST(b != e); + BOOST_TEST(!(b == e)); + { + I i; + I i2(b); //CopyConstructible + i = i2; //Assignable + //Destructible + (void)i; + (void)i2; + } + + typedef typename iterator_traits<I>::reference reference; + reference r = *b; + (void)r; + typedef typename iterator_traits<I>::pointer pointer; + pointer p = (iterator_arrow_result)(b); + (void)p; + I &ri= ++b; + (void)ri; + const I &cri= b++; + (void)cri; +} + +template<class C> +void test_iterator_compatible(C &c) +{ + typedef typename C::iterator iterator; + typedef typename C::const_iterator const_iterator; + typedef typename get_reverse_iterator<C>::type reverse_iterator; + typedef typename get_const_reverse_iterator<C>::type const_reverse_iterator; + //Basic operations + test_iterator_operations(c. begin(), c. end()); + test_iterator_operations(c.cbegin(), c.cend()); + test_iterator_operations(get_reverse_iterator<C>::begin(c), get_reverse_iterator<C>::end(c)); + test_iterator_operations(get_const_reverse_iterator<C>::begin(c), get_const_reverse_iterator<C>::end(c)); + //Make sure dangeous conversions are not possible + BOOST_STATIC_ASSERT((!boost::intrusive::detail::is_convertible<const_iterator, iterator>::value)); + BOOST_STATIC_ASSERT((!boost::intrusive::detail::is_convertible<const_reverse_iterator, reverse_iterator>::value)); + //Test iterator conversions + { + const_iterator ci; + iterator i(c.begin()); + ci = i; + (void)ci; + BOOST_ASSERT(ci == i); + BOOST_ASSERT(*ci == *i); + const_iterator ci2(i); + BOOST_ASSERT(ci2 == i); + BOOST_ASSERT(*ci2 == *i); + (void)ci2; + } + //Test reverse_iterator conversions + { + const_reverse_iterator cr; + reverse_iterator r(get_reverse_iterator<C>::begin(c)); + cr = r; + BOOST_ASSERT(cr == r); + BOOST_ASSERT(*cr == *r); + const_reverse_iterator cr2(r); + BOOST_ASSERT(cr2 == r); + BOOST_ASSERT(*cr2 == *r); + (void)cr2; + } +} + +template<class C> +void test_iterator_input_and_compatible(C &c) +{ + typedef typename C::iterator iterator; + typedef typename C::const_iterator const_iterator; + typedef typename get_reverse_iterator<C>::type reverse_iterator; + typedef typename get_const_reverse_iterator<C>::type const_reverse_iterator; + typedef iterator_traits<iterator> nit_traits; + typedef iterator_traits<const_iterator> cit_traits; + typedef iterator_traits<reverse_iterator> rnit_traits; + typedef iterator_traits<const_reverse_iterator> crit_traits; + + using boost::move_detail::is_same; + //Trivial typedefs + BOOST_STATIC_ASSERT((!is_same<iterator, const_iterator>::value)); + BOOST_STATIC_ASSERT((!is_same<reverse_iterator, const_reverse_iterator>::value)); + //difference_type + typedef typename C::difference_type difference_type; + BOOST_STATIC_ASSERT((is_same<difference_type, typename nit_traits::difference_type>::value)); + BOOST_STATIC_ASSERT((is_same<difference_type, typename cit_traits::difference_type>::value)); + BOOST_STATIC_ASSERT((is_same<difference_type, typename rnit_traits::difference_type>::value)); + BOOST_STATIC_ASSERT((is_same<difference_type, typename crit_traits::difference_type>::value)); + //value_type + typedef typename C::value_type value_type; + BOOST_STATIC_ASSERT((is_same<value_type, typename nit_traits::value_type>::value)); + BOOST_STATIC_ASSERT((is_same<value_type, typename cit_traits::value_type>::value)); + BOOST_STATIC_ASSERT((is_same<value_type, typename rnit_traits::value_type>::value)); + BOOST_STATIC_ASSERT((is_same<value_type, typename crit_traits::value_type>::value)); + //pointer + typedef typename C::pointer pointer; + typedef typename C::const_pointer const_pointer; + BOOST_STATIC_ASSERT((is_same<pointer, typename nit_traits::pointer>::value)); + BOOST_STATIC_ASSERT((is_same<const_pointer, typename cit_traits::pointer>::value)); + BOOST_STATIC_ASSERT((is_same<pointer, typename rnit_traits::pointer>::value)); + BOOST_STATIC_ASSERT((is_same<const_pointer, typename crit_traits::pointer>::value)); + //reference + typedef typename C::reference reference; + typedef typename C::const_reference const_reference; + BOOST_STATIC_ASSERT((is_same<reference, typename nit_traits::reference>::value)); + BOOST_STATIC_ASSERT((is_same<const_reference, typename cit_traits::reference>::value)); + BOOST_STATIC_ASSERT((is_same<reference, typename rnit_traits::reference>::value)); + BOOST_STATIC_ASSERT((is_same<const_reference, typename crit_traits::reference>::value)); + //Dynamic tests + test_iterator_compatible(c); +} + +template<class C, class I> +void test_iterator_forward_functions(C const &c, I const b, I const e) +{ + typedef typename C::size_type size_type; + { + size_type i = 0; + I it = b; + for(I it2 = b; i != c.size(); ++it, ++i){ + BOOST_TEST(it == it2++); + I ittmp(it); + I *iaddr = &ittmp; + BOOST_TEST(&(++ittmp) == iaddr); + BOOST_TEST(ittmp == it2); + } + BOOST_TEST(i == c.size()); + BOOST_TEST(it == e); + } +} + +template<class C> +void test_iterator_forward_and_compatible(C &c) +{ + test_iterator_input_and_compatible(c); + test_iterator_forward_functions(c, c.begin(), c.end()); + test_iterator_forward_functions(c, c.cbegin(), c.cend()); + test_iterator_forward_functions(c, get_reverse_iterator<C>::begin(c), get_reverse_iterator<C>::end(c)); + test_iterator_forward_functions(c, get_const_reverse_iterator<C>::begin(c), get_const_reverse_iterator<C>::end(c)); +} + +template<class C, class I> +void test_iterator_bidirectional_functions(C const &c, I const b, I const e) +{ + typedef typename C::size_type size_type; + { + size_type i = 0; + I it = e; + for(I it2 = e; i != c.size(); --it, ++i){ + BOOST_TEST(it == it2--); + I ittmp(it); + I*iaddr = &ittmp; + BOOST_TEST(&(--ittmp) == iaddr); + BOOST_TEST(ittmp == it2); + BOOST_TEST((++ittmp) == it); + } + BOOST_TEST(i == c.size()); + BOOST_TEST(it == b); + } +} + +template<class C> +void test_iterator_bidirectional_and_compatible(C &c) +{ + test_iterator_forward_and_compatible(c); + test_iterator_bidirectional_functions(c, c.begin(), c.end()); + test_iterator_bidirectional_functions(c, c.cbegin(), c.cend()); + test_iterator_bidirectional_functions(c, c.rbegin(), c.rend()); + test_iterator_bidirectional_functions(c, c.crbegin(), c.crend()); +} + +template<class C, class I> +void test_iterator_random_functions(C const &c, I const b, I const e) +{ + typedef typename C::size_type size_type; + { + I it = b; + for(size_type i = 0, m = c.size(); i != m; ++i, ++it){ + BOOST_TEST(i == size_type(it - b)); + BOOST_TEST(b[i] == *it); + BOOST_TEST(&b[i] == &*it); + BOOST_TEST((b + i) == it); + BOOST_TEST((i + b) == it); + BOOST_TEST(b == (it - i)); + I tmp(b); + BOOST_TEST((tmp+=i) == it); + tmp = it; + BOOST_TEST(b == (tmp-=i)); + } + BOOST_TEST(c.size() == size_type(e - b)); + } + { + I it(b), itb(b); + if(b != e){ + for(++it; it != e; ++it){ + BOOST_TEST(itb < it); + BOOST_TEST(itb <= it); + BOOST_TEST(!(itb > it)); + BOOST_TEST(!(itb >= it)); + BOOST_TEST(it > itb); + BOOST_TEST(it >= itb); + BOOST_TEST(!(it < itb)); + BOOST_TEST(!(it <= itb)); + BOOST_TEST(it >= it); + BOOST_TEST(it <= it); + itb = it; + } + } + } +} + +template<class C> +void test_iterator_random_and_compatible(C &c) +{ + test_iterator_bidirectional_and_compatible(c); + test_iterator_random_functions(c, c.begin(), c.end()); + test_iterator_random_functions(c, c.cbegin(), c.cend()); + test_iterator_random_functions(c, c.rbegin(), c.rend()); + test_iterator_random_functions(c, c.crbegin(), c.crend()); +} + +//////////////////////// + +template<class C> +void test_iterator_forward(C &c) +{ + typedef typename C::iterator iterator; + typedef typename C::const_iterator const_iterator; + typedef typename get_reverse_iterator<C>::type reverse_iterator; + typedef typename get_const_reverse_iterator<C>::type const_reverse_iterator; + typedef iterator_traits<iterator> nit_traits; + typedef iterator_traits<const_iterator> cit_traits; + typedef iterator_traits<reverse_iterator> rnit_traits; + typedef iterator_traits<const_reverse_iterator> crit_traits; + + using boost::intrusive::detail::is_same; + //iterator_category + BOOST_STATIC_ASSERT((is_same<std::forward_iterator_tag, typename nit_traits::iterator_category>::value)); + BOOST_STATIC_ASSERT((is_same<std::forward_iterator_tag, typename cit_traits::iterator_category>::value)); + BOOST_STATIC_ASSERT((is_same<std::forward_iterator_tag, typename rnit_traits::iterator_category>::value)); + BOOST_STATIC_ASSERT((is_same<std::forward_iterator_tag, typename crit_traits::iterator_category>::value)); + //Test dynamic + test_iterator_forward_and_compatible(c); +} + +template<class C> +void test_iterator_bidirectional(C &c) +{ + typedef typename C::iterator iterator; + typedef typename C::const_iterator const_iterator; + typedef typename C::reverse_iterator reverse_iterator; + typedef typename C::const_reverse_iterator const_reverse_iterator; + typedef iterator_traits<iterator> nit_traits; + typedef iterator_traits<const_iterator> cit_traits; + typedef iterator_traits<reverse_iterator> rnit_traits; + typedef iterator_traits<const_reverse_iterator> crit_traits; + + using boost::intrusive::detail::is_same; + //iterator_category + BOOST_STATIC_ASSERT((is_same<std::bidirectional_iterator_tag, typename nit_traits::iterator_category>::value)); + BOOST_STATIC_ASSERT((is_same<std::bidirectional_iterator_tag, typename cit_traits::iterator_category>::value)); + BOOST_STATIC_ASSERT((is_same<std::bidirectional_iterator_tag, typename rnit_traits::iterator_category>::value)); + BOOST_STATIC_ASSERT((is_same<std::bidirectional_iterator_tag, typename crit_traits::iterator_category>::value)); + //Test dynamic + test_iterator_bidirectional_and_compatible(c); +} + +template<class C> +void test_iterator_random(C &c) +{ + typedef typename C::iterator iterator; + typedef typename C::const_iterator const_iterator; + typedef typename C::reverse_iterator reverse_iterator; + typedef typename C::const_reverse_iterator const_reverse_iterator; + typedef iterator_traits<iterator> nit_traits; + typedef iterator_traits<const_iterator> cit_traits; + typedef iterator_traits<reverse_iterator> rnit_traits; + typedef iterator_traits<const_reverse_iterator> crit_traits; + + using boost::intrusive::detail::is_same; + //iterator_category + BOOST_STATIC_ASSERT((is_same<std::random_access_iterator_tag, typename nit_traits::iterator_category>::value)); + BOOST_STATIC_ASSERT((is_same<std::random_access_iterator_tag, typename cit_traits::iterator_category>::value)); + BOOST_STATIC_ASSERT((is_same<std::random_access_iterator_tag, typename rnit_traits::iterator_category>::value)); + BOOST_STATIC_ASSERT((is_same<std::random_access_iterator_tag, typename crit_traits::iterator_category>::value)); + //Test dynamic + test_iterator_random_and_compatible(c); +} + +}}} //boost::container::test diff --git a/src/boost/libs/intrusive/test/itestvalue.hpp b/src/boost/libs/intrusive/test/itestvalue.hpp new file mode 100644 index 00000000..1a4ecdae --- /dev/null +++ b/src/boost/libs/intrusive/test/itestvalue.hpp @@ -0,0 +1,284 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2013. +// +// 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_ITESTVALUE_HPP +#define BOOST_INTRUSIVE_DETAIL_ITESTVALUE_HPP + +#include <iostream> +#include <boost/intrusive/options.hpp> +#include <boost/functional/hash.hpp> +#include <boost/intrusive/pointer_traits.hpp> +#include "nonhook_node.hpp" +#include "int_holder.hpp" +#include <boost/intrusive/detail/get_value_traits.hpp> +#include <boost/container/vector.hpp> + +namespace boost{ +namespace intrusive{ + +struct testvalue_filler +{ + void *dummy_[3]; +}; + +template<class Hooks> +struct testvalue + : testvalue_filler + , Hooks::base_hook_type + , Hooks::auto_base_hook_type +{ + typename Hooks::member_hook_type node_; + typename Hooks::auto_member_hook_type auto_node_; + typename Hooks::nonhook_node_member_type nhn_member_; + + int_holder value_; + + testvalue() + {} + + explicit testvalue(int i) + : value_(i) + {} + + testvalue (const testvalue& src) + : value_(src.value_) + {} + + // testvalue is used in boost::container::vector and thus prev and next + // have to be handled appropriately when copied: + testvalue & operator= (const testvalue& src) + { + Hooks::base_hook_type::operator=(static_cast<const typename Hooks::base_hook_type&>(src)); + Hooks::auto_base_hook_type::operator=(static_cast<const typename Hooks::auto_base_hook_type&>(src)); + this->node_ = src.node_; + this->auto_node_ = src.auto_node_; + this->nhn_member_ = src.nhn_member_; + value_ = src.value_; + return *this; + } + + void swap_nodes(testvalue &other) + { + Hooks::base_hook_type::swap_nodes(static_cast<typename Hooks::base_hook_type&>(other)); + Hooks::auto_base_hook_type::swap_nodes(static_cast<typename Hooks::auto_base_hook_type&>(other)); + node_.swap_nodes(other.node_); + auto_node_.swap_nodes(other.auto_node_); + nhn_member_.swap_nodes(other.nhn_member_); + } + + bool is_linked() const + { + return Hooks::base_hook_type::is_linked() || + Hooks::auto_base_hook_type::is_linked() || + node_.is_linked() || + auto_node_.is_linked() || + nhn_member_.is_linked(); + } + + const int_holder &get_int_holder() const + { return value_; } + + int int_value() const + { return value_.int_value(); } + + ~testvalue() + {} + + bool operator< (const testvalue &other) const + { return value_ < other.value_; } + + bool operator> (const testvalue &other) const + { return value_ > other.value_; } + + bool operator==(const testvalue &other) const + { return value_ == other.value_; } + + bool operator!=(const testvalue &other) const + { return value_ != other.value_; } + + friend bool operator< (int other1, const testvalue &other2) + { return other1 < other2.value_.int_; } + + friend bool operator> (int other1, const testvalue &other2) + { return other1 > other2.value_.int_; } + + friend bool operator< (const testvalue &other1, int other2) + { return other1.value_.int_ < other2; } + + friend bool operator> (const testvalue &other1, int other2) + { return other1.value_.int_ > other2; } + + friend bool operator== (int other1, const testvalue &other2) + { return other1 == other2.value_.int_; } + + friend bool operator== (const testvalue &other1, int other2) + { return other1.value_.int_ == other2; } + + friend bool operator!= (int other1, const testvalue &other2) + { return other1 != other2.value_.int_; } + + friend bool operator!= (const testvalue &other1, int other2) + { return other1.value_.int_ != other2; } + + friend std::size_t hash_value(const testvalue&t) + { + boost::hash<int> hasher; + return hasher((&t)->int_value()); + } +}; + +template<class T> +std::size_t priority_hash(const T &t) +{ return boost::hash<int>()((&t)->int_value()); } + +std::size_t priority_hash(int i) +{ return boost::hash<int>()(i); } + +template <class T, class U> +bool priority_order(const T& t1, const U& t2) +{ + std::size_t hash1 = (priority_hash)(t1); + boost::hash_combine(hash1, -hash1); + std::size_t hash2 = (priority_hash)(t2); + boost::hash_combine(hash2, -hash2); + return hash1 < hash2; +} + +template < typename Node_Algorithms, class Hooks> +void swap_nodes(testvalue<Hooks>& lhs, testvalue<Hooks>& rhs) +{ + lhs.swap_nodes(rhs); +} + +template<class Hooks> +std::ostream& operator<< + (std::ostream& s, const testvalue<Hooks>& t) +{ return s << t.value_.int_value(); } + +struct even_odd +{ + template < typename key_type_1, typename key_type_2 > + bool operator() + (const key_type_1& v1 + ,const key_type_2& v2) const + { + if (((&v1)->int_value() & 1) == ((&v2)->int_value() & 1)) + return (&v1)->int_value() < (&v2)->int_value(); + else + return (&v2)->int_value() & 1; + } +}; + +struct is_even +{ + template <typename key_type> + bool operator() + (const key_type& v1) const + { return ((&v1)->int_value() & 1) == 0; } +}; + +struct is_odd +{ + template <typename key_type> + bool operator() + (const key_type& v1) const + { return ((&v1)->int_value() & 1) != 0; } +}; + +template <typename> +struct ValueContainer; + +template < class Hooks> +struct ValueContainer< testvalue<Hooks> > +{ + typedef boost::container::vector< testvalue<Hooks> > type; +}; + +template < typename Pointer > +class heap_node_holder +{ + typedef typename pointer_traits<Pointer>::element_type element_type; + typedef Pointer pointer; + typedef typename pointer_rebind<pointer, const element_type>::type const_pointer; + + public: + heap_node_holder() + : m_ptr(pointer_traits<Pointer>::pointer_to(*new element_type)) + {} + + ~heap_node_holder() + { delete &*m_ptr; } + + const_pointer get_node() const + { return m_ptr; } + + pointer get_node() + { return m_ptr; } + + private: + pointer m_ptr; +}; + +template<class Hooks> +struct testvalue_traits + : public Hooks +{ + typedef testvalue< Hooks > value_type; + + //base + typedef typename detail::get_base_value_traits + < value_type + , typename Hooks::base_hook_type + >::type base_value_traits; + //auto-base + typedef typename detail::get_base_value_traits + < value_type + , typename Hooks::auto_base_hook_type + >::type auto_base_value_traits; + //member + typedef typename detail::get_member_value_traits + < member_hook + < value_type + , typename Hooks::member_hook_type + , &value_type::node_ + > + >::type member_value_traits; + //auto-member + typedef typename detail::get_member_value_traits + < member_hook + < value_type + , typename Hooks::auto_member_hook_type + , &value_type::auto_node_ + > + >::type auto_member_value_traits; + //nonmember + typedef nonhook_node_member_value_traits + < value_type + , typename Hooks::nonhook_node_member_type + , &value_type::nhn_member_ + , safe_link + > nonhook_value_traits; +}; + +} //namespace intrusive{ +} //namespace boost{ + +bool priority_order(int t1, int t2) +{ + std::size_t hash1 = boost::hash<int>()(t1); + boost::hash_combine(hash1, &t1); + std::size_t hash2 = boost::hash<int>()(t2); + boost::hash_combine(hash2, &t2); + return hash1 < hash2; +} + +#endif diff --git a/src/boost/libs/intrusive/test/list_test.cpp b/src/boost/libs/intrusive/test/list_test.cpp new file mode 100644 index 00000000..e756a917 --- /dev/null +++ b/src/boost/libs/intrusive/test/list_test.cpp @@ -0,0 +1,515 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2013. +// +// 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 <boost/intrusive/list.hpp> +#include <boost/intrusive/pointer_traits.hpp> +#include "itestvalue.hpp" +#include "bptr_value.hpp" +#include "smart_ptr.hpp" +#include "common_functors.hpp" +#include <vector> +#include <boost/detail/lightweight_test.hpp> +#include "test_macros.hpp" +#include "test_container.hpp" +#include <typeinfo> + +using namespace boost::intrusive; + +template<class VoidPointer> +struct hooks +{ + typedef list_base_hook<void_pointer<VoidPointer> > base_hook_type; + typedef list_base_hook< link_mode<auto_unlink> + , void_pointer<VoidPointer>, tag<void> > auto_base_hook_type; + typedef list_member_hook<void_pointer<VoidPointer>, tag<void> > member_hook_type; + typedef list_member_hook< link_mode<auto_unlink> + , void_pointer<VoidPointer> > auto_member_hook_type; + typedef nonhook_node_member< list_node_traits< VoidPointer >, + circular_list_algorithms > nonhook_node_member_type; +}; + + +template < typename ListType, typename ValueContainer > +struct test_list +{ + typedef ListType list_type; + typedef typename list_type::value_traits value_traits; + typedef typename value_traits::value_type value_type; + typedef typename list_type::node_algorithms node_algorithms; + + static void test_all(ValueContainer&); + static void test_front_back(ValueContainer&); + static void test_sort(ValueContainer&); + static void test_merge(ValueContainer&); + static void test_remove_unique(ValueContainer&); + static void test_insert(ValueContainer&); + static void test_shift(ValueContainer&); + static void test_swap(ValueContainer&); + static void test_clone(ValueContainer&); + static void test_container_from_end(ValueContainer&, detail::true_type); + static void test_container_from_end(ValueContainer&, detail::false_type) {} +}; + +template < typename ListType, typename ValueContainer > +void test_list< ListType, ValueContainer >::test_all(ValueContainer& values) +{ + { + list_type list(values.begin(), values.end()); + test::test_container(list); + list.clear(); + list.insert(list.end(), values.begin(), values.end()); + test::test_sequence_container(list, values); + } + { + list_type list(values.begin(), values.end()); + test::test_iterator_bidirectional(list); + } + + test_front_back(values); + test_sort(values); + test_merge(values); + test_remove_unique(values); + test_insert(values); + test_shift(values); + test_swap(values); + test_clone(values); + test_container_from_end(values, detail::bool_< ListType::has_container_from_iterator >()); +} + +//test: push_front, pop_front, push_back, pop_back, front, back, size, empty: +template < class ListType, typename ValueContainer > +void test_list< ListType, ValueContainer > + ::test_front_back(ValueContainer& values) +{ + list_type testlist; + BOOST_TEST (testlist.empty()); + + testlist.push_back (values[0]); + BOOST_TEST (testlist.size() == 1); + BOOST_TEST (&testlist.front() == &values[0]); + BOOST_TEST (&testlist.back() == &values[0]); + + testlist.push_front (values[1]); + BOOST_TEST (testlist.size() == 2); + BOOST_TEST (&testlist.front() == &values[1]); + BOOST_TEST (&testlist.back() == &values[0]); + + testlist.pop_back(); + BOOST_TEST (testlist.size() == 1); + const list_type &const_testlist = testlist; + BOOST_TEST (&const_testlist.front() == &values[1]); + BOOST_TEST (&const_testlist.back() == &values[1]); + + testlist.pop_front(); + BOOST_TEST (testlist.empty()); +} + +//test: constructor, iterator, reverse_iterator, sort, reverse: +template < class ListType, typename ValueContainer > +void test_list< ListType, ValueContainer > + ::test_sort(ValueContainer& values) +{ + list_type testlist(values.begin(), values.end()); + + { int init_values [] = { 1, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); } + + testlist.sort (even_odd()); + { int init_values [] = { 5, 3, 1, 4, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist.rbegin() ); } + + testlist.reverse(); + { int init_values [] = { 5, 3, 1, 4, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); } +} + +//test: merge due to error in merge implementation: +template < class ListType, typename ValueContainer > +void test_list< ListType, ValueContainer > + ::test_remove_unique (ValueContainer& values) +{ + { + list_type list(values.begin(), values.end()); + list.remove_if(is_even()); + int init_values [] = { 1, 3, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() ); + } + { + list_type list(values.begin(), values.end()); + list.remove_if(is_odd()); + int init_values [] = { 2, 4 }; + TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() ); + } + { + list_type list(values.begin(), values.end()); + list.remove_and_dispose_if(is_even(), test::empty_disposer()); + int init_values [] = { 1, 3, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() ); + } + { + list_type list(values.begin(), values.end()); + list.remove_and_dispose_if(is_odd(), test::empty_disposer()); + int init_values [] = { 2, 4 }; + TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() ); + } + { + ValueContainer values2(values); + list_type list(values.begin(), values.end()); + list.insert(list.end(), values2.begin(), values2.end()); + list.sort(); + int init_values [] = { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() ); + list.unique(); + int init_values2 [] = { 1, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values2, list.begin() ); + } +} + +//test: merge due to error in merge implementation: +template < class ListType, typename ValueContainer > +void test_list< ListType, ValueContainer > + ::test_merge (ValueContainer& values) +{ + list_type testlist1, testlist2; + testlist1.push_front (values[0]); + testlist2.push_front (values[4]); + testlist2.push_front (values[3]); + testlist2.push_front (values[2]); + testlist1.merge (testlist2); + + int init_values [] = { 1, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); +} + +//test: assign, insert, const_iterator, const_reverse_iterator, erase, s_iterator_to: +template < class ListType, typename ValueContainer > +void test_list< ListType, ValueContainer > + ::test_insert(ValueContainer& values) +{ + list_type testlist; + testlist.assign (values.begin() + 2, values.begin() + 5); + + const list_type& const_testlist = testlist; + { int init_values [] = { 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); } + + typename list_type::iterator i = ++testlist.begin(); + BOOST_TEST (i->value_ == 4); + + { + typename list_type::const_iterator ci = typename list_type::iterator(); + (void)ci; + } + + testlist.insert (i, values[0]); + { int init_values [] = { 5, 4, 1, 3 }; + TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.rbegin() ); } + + i = testlist.iterator_to (values[4]); + BOOST_TEST (&*i == &values[4]); + + i = list_type::s_iterator_to (values[4]); + BOOST_TEST (&*i == &values[4]); + + typename list_type::const_iterator ic; + ic = testlist.iterator_to (static_cast< typename list_type::const_reference >(values[4])); + BOOST_TEST (&*ic == &values[4]); + + ic = list_type::s_iterator_to (static_cast< typename list_type::const_reference >(values[4])); + BOOST_TEST (&*ic == &values[4]); + + i = testlist.erase (i); + BOOST_TEST (i == testlist.end()); + + { int init_values [] = { 3, 1, 4 }; + TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); } +} + +template < class ListType, typename ValueContainer > +void test_list< ListType, ValueContainer > + ::test_shift(ValueContainer& values) +{ + list_type testlist; + const int num_values = (int)values.size(); + std::vector<int> expected_values(num_values); + + for(int s = 1; s <= num_values; ++s){ + expected_values.resize(s); + //Shift forward all possible positions 3 times + for(int i = 0; i < s*3; ++i){ + testlist.insert(testlist.begin(), values.begin(), values.begin() + s); + testlist.shift_forward(i); + for(int j = 0; j < s; ++j){ + expected_values[(j + s - i%s) % s] = (j + 1); + } + TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin()); + testlist.clear(); + } + + //Shift backwards all possible positions + for(int i = 0; i < s*3; ++i){ + testlist.insert(testlist.begin(), values.begin(), values.begin() + s); + testlist.shift_backwards(i); + for(int j = 0; j < s; ++j){ + expected_values[(j + i) % s] = (j + 1); + } + TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin()); + testlist.clear(); + } + } +} + +//test: insert (seq-version), swap, splice, erase (seq-version): +template < class ListType, typename ValueContainer > +void test_list< ListType, ValueContainer > + ::test_swap(ValueContainer& values) +{ + { + list_type testlist1 (values.begin(), values.begin() + 2); + list_type testlist2; + testlist2.insert (testlist2.end(), values.begin() + 2, values.begin() + 5); + testlist1.swap (testlist2); + + { int init_values [] = { 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + { int init_values [] = { 1, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } + + testlist2.splice (++testlist2.begin(), testlist1); + { int init_values [] = { 1, 3, 4, 5, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } + + BOOST_TEST (testlist1.empty()); + + testlist1.splice (testlist1.end(), testlist2, ++(++testlist2.begin())); + { int init_values [] = { 4 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + + { int init_values [] = { 1, 3, 5, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } + + testlist1.splice (testlist1.end(), testlist2, + testlist2.begin(), ----testlist2.end()); + { int init_values [] = { 4, 1, 3 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + { int init_values [] = { 5, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } + + testlist1.erase (testlist1.iterator_to(values[0]), testlist1.end()); + BOOST_TEST (testlist1.size() == 1); + BOOST_TEST (&testlist1.front() == &values[3]); + } + { + list_type testlist1 (values.begin(), values.begin() + 2); + list_type testlist2 (values.begin() + 3, values.begin() + 5); + + swap_nodes< node_algorithms >(values[0], values[2]); + { int init_values [] = { 3, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + + swap_nodes< node_algorithms >(values[2], values[4]); + { int init_values [] = { 5, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + { int init_values [] = { 4, 3 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } + } + { + list_type testlist1 (values.begin(), values.begin() + 1); + + { int init_values [] = { 1 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + + swap_nodes< node_algorithms >(values[1], values[2]); + + { int init_values [] = { 1 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + + swap_nodes< node_algorithms >(values[0], values[2]); + + { int init_values [] = { 3 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + + swap_nodes< node_algorithms >(values[0], values[2]); + + { int init_values [] = { 1 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + } +} + +template < class ListType, typename ValueContainer > +void test_list< ListType, ValueContainer > + ::test_container_from_end(ValueContainer& values, detail::true_type) +{ + list_type testlist1 (values.begin(), values.begin() + values.size()); + BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.end())); + BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.cend())); +} + +template < class ListType, typename ValueContainer > +void test_list< ListType, ValueContainer > + ::test_clone(ValueContainer& values) +{ + list_type testlist1 (values.begin(), values.begin() + values.size()); + list_type testlist2; + + testlist2.clone_from(testlist1, test::new_cloner<value_type>(), test::delete_disposer<value_type>()); + BOOST_TEST (testlist2 == testlist1); + testlist2.clear_and_dispose(test::delete_disposer<value_type>()); + BOOST_TEST (testlist2.empty()); +} + +template < typename ValueTraits, bool ConstantTimeSize, bool Default_Holder, typename ValueContainer > +struct make_and_test_list + : test_list< list< typename ValueTraits::value_type, + value_traits< ValueTraits >, + size_type< std::size_t >, + constant_time_size< ConstantTimeSize > + >, + ValueContainer + > +{}; + +template < typename ValueTraits, bool ConstantTimeSize, typename ValueContainer > +struct make_and_test_list< ValueTraits, ConstantTimeSize, false, ValueContainer > + : test_list< list< typename ValueTraits::value_type, + value_traits< ValueTraits >, + size_type< std::size_t >, + constant_time_size< ConstantTimeSize >, + header_holder_type< heap_node_holder< typename ValueTraits::pointer > > + >, + ValueContainer + > +{}; + + +template < class VoidPointer, bool ConstantTimeSize, bool Default_Holder > +class test_main_template +{ + public: + int operator()() + { + typedef testvalue< hooks<VoidPointer> > value_type; + std::vector<value_type> data (5); + for (int i = 0; i < 5; ++i) + data[i].value_ = i + 1; + + make_and_test_list < typename detail::get_base_value_traits < + value_type, + typename hooks<VoidPointer>::base_hook_type + >::type, + ConstantTimeSize, + Default_Holder, + std::vector< value_type > + >::test_all(data); + make_and_test_list < typename detail::get_member_value_traits < + member_hook< value_type, typename hooks<VoidPointer>::member_hook_type, &value_type::node_> + >::type, + ConstantTimeSize, + Default_Holder, + std::vector< value_type > + >::test_all(data); + make_and_test_list< nonhook_node_member_value_traits < + value_type, + typename hooks<VoidPointer>::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + >, + ConstantTimeSize, + Default_Holder, + std::vector< value_type > + >::test_all(data); + + return 0; + } +}; + +template < class VoidPointer, bool Default_Holder > +class test_main_template< VoidPointer, false, Default_Holder > +{ + public: + int operator()() + { + typedef testvalue< hooks<VoidPointer> > value_type; + std::vector<value_type> data (5); + for (int i = 0; i < 5; ++i) + data[i].value_ = i + 1; + + make_and_test_list < typename detail::get_base_value_traits < + value_type, + typename hooks<VoidPointer>::auto_base_hook_type + >::type, + false, + Default_Holder, + std::vector< value_type > + >::test_all(data); + make_and_test_list < typename detail::get_member_value_traits < + member_hook< value_type, typename hooks<VoidPointer>::auto_member_hook_type, &value_type::auto_node_> + >::type, + false, + Default_Holder, + std::vector< value_type > + >::test_all(data); + + return 0; + } +}; + +template < bool ConstantTimeSize > +struct test_main_template_bptr +{ + int operator()() + { + typedef BPtr_Value value_type; + typedef BPtr_Value_Traits< List_BPtr_Node_Traits > list_value_traits; + typedef typename list_value_traits::node_ptr node_ptr; + typedef bounded_allocator< value_type > allocator_type; + + bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope; + + allocator_type allocator; + + { + bounded_reference_cont< value_type > ref_cont; + for (int i = 0; i < 5; ++i) + { + node_ptr tmp = allocator.allocate(1); + new (tmp.raw()) value_type(i + 1); + ref_cont.push_back(*tmp); + } + + test_list < list < value_type, + value_traits< list_value_traits >, + size_type< std::size_t >, + constant_time_size< ConstantTimeSize >, + header_holder_type< bounded_pointer_holder< value_type > > + >, + bounded_reference_cont< value_type > + >::test_all(ref_cont); + } + + return 0; + } +}; + +int main() +{ + // test (plain/smart pointers) x (nonconst/const size) x (void node allocator) + test_main_template<void*, false, true>()(); + test_main_template<boost::intrusive::smart_ptr<void>, false, true>()(); + test_main_template<void*, true, true>()(); + test_main_template<boost::intrusive::smart_ptr<void>, true, true>()(); + // test (bounded pointers) x ((nonconst/const size) x (special node allocator) + test_main_template_bptr< true >()(); + test_main_template_bptr< false >()(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/intrusive/test/make_functions_test.cpp b/src/boost/libs/intrusive/test/make_functions_test.cpp new file mode 100644 index 00000000..8d0fafbe --- /dev/null +++ b/src/boost/libs/intrusive/test/make_functions_test.cpp @@ -0,0 +1,213 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2013 +// +// 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 <boost/intrusive/list.hpp> +#include <boost/intrusive/slist.hpp> +#include <boost/intrusive/set.hpp> +#include <boost/intrusive/unordered_set.hpp> +#include <boost/intrusive/avl_set.hpp> +#include <boost/intrusive/sg_set.hpp> +#include <boost/intrusive/splay_set.hpp> +#include <boost/intrusive/bs_set.hpp> +#include <boost/intrusive/treap_set.hpp> +#include <boost/intrusive/detail/mpl.hpp> +#include <boost/intrusive/pointer_traits.hpp> +#include <boost/static_assert.hpp> +#include "smart_ptr.hpp" +#include <vector> + +using namespace boost::intrusive; + +struct my_tag; +struct my_tag2; +struct my_tag3; + +typedef make_bs_set_base_hook + < void_pointer<smart_ptr<void> >, link_mode<normal_link> + , tag<my_tag> >::type TreapHook; +typedef make_bs_set_base_hook + < void_pointer<smart_ptr<void> >, link_mode<normal_link> + , tag<my_tag2> >::type SplayHook; +typedef make_bs_set_base_hook + < void_pointer<smart_ptr<void> >, link_mode<normal_link> + , tag<my_tag3> >::type BsHook; + +class MyClass +: public make_list_base_hook + < void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type +, public make_slist_base_hook + < void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type +, public make_set_base_hook + < void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type +, public make_unordered_set_base_hook + < void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type +, public make_avl_set_base_hook + < void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type +, public make_bs_set_base_hook + < void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type +, public TreapHook +, public SplayHook +, public BsHook +{ + int int_; + + public: + MyClass(int i) + : int_(i) + {} + + friend bool operator<(const MyClass &l, const MyClass &r) + { return l.int_ < r.int_; } + + friend bool operator==(const MyClass &l, const MyClass &r) + { return l.int_ == r.int_; } + + friend std::size_t hash_value(const MyClass &v) + { return boost::hash_value(v.int_); } + + friend bool priority_order(const MyClass &l, const MyClass &r) + { return l.int_ < r.int_; } +}; + +//Define a list that will store MyClass using the public base hook +typedef make_list<MyClass>::type List; +typedef make_slist<MyClass>::type Slist; +typedef make_set<MyClass>::type Set; +typedef make_unordered_set<MyClass>::type USet; + +typedef make_avl_set<MyClass>::type AvlSet; +typedef make_sg_set<MyClass>::type SgSet; +typedef make_treap_set<MyClass + , base_hook<TreapHook> >::type TreapSet; +typedef make_splay_set<MyClass + , base_hook<SplayHook> >::type SplaySet; +typedef make_bs_set<MyClass + , base_hook<BsHook> >::type BsSet; + +int main() +{ + typedef std::vector<MyClass>::iterator VectIt; + typedef std::vector<MyClass>::reverse_iterator VectRit; + + //Create several MyClass objects, each one with a different value + std::vector<MyClass> values; + for(int i = 0; i < 100; ++i) values.push_back(MyClass(i)); + + USet::bucket_type buckets[100]; + + List my_list; + Slist my_slist; + Set my_set; + USet my_uset(USet::bucket_traits + (pointer_traits<USet::bucket_ptr>::pointer_to(buckets[0]), 100)); + + AvlSet my_avlset; + SplaySet my_splayset; + BsSet my_bsset; + SgSet my_sgset; + TreapSet my_treapset; + + //Now insert them in containers + for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){ + my_list.push_front(*it); + my_slist.push_front(*it); + my_set.insert(*it); + my_uset.insert(*it); + my_avlset.insert(*it); + my_splayset.insert(*it); + my_bsset.insert(*it); + my_sgset.insert(*it); + my_treapset.insert(*it); + } + + //Now test lists + { + List::const_iterator list_it(my_list.cbegin()); + Slist::const_iterator slist_it(my_slist.cbegin()); + Set::const_reverse_iterator set_rit(my_set.crbegin()); + + AvlSet::const_reverse_iterator avlset_rit(my_avlset.crbegin()); + SplaySet::const_reverse_iterator splayset_rit(my_splayset.crbegin()); + BsSet::const_reverse_iterator bsset_rit(my_bsset.crbegin()); + SgSet::const_reverse_iterator sgset_rit(my_sgset.crbegin()); + TreapSet::const_reverse_iterator treapset_rit(my_treapset.crbegin()); + + VectRit vect_it(values.rbegin()), vect_itend(values.rend()); + + //Test the objects inserted in the base hook list + for( ; vect_it != vect_itend + ; ++vect_it, ++list_it, ++slist_it, ++set_rit + , ++avlset_rit, ++splayset_rit, ++bsset_rit, ++sgset_rit, ++treapset_rit + ){ + if(&*list_it != &*vect_it) return 1; + if(&*slist_it != &*vect_it) return 1; + if(&*set_rit != &*vect_it) return 1; + if(my_uset.find(*set_rit) == my_uset.cend()) return 1; + if(&*avlset_rit != &*vect_it) return 1; + if(&*splayset_rit != &*vect_it) return 1; + if(&*bsset_rit != &*vect_it) return 1; + if(&*sgset_rit != &*vect_it) return 1; + if(&*treapset_rit != &*vect_it) return 1; + } + } + + //Check defined types and implicitly defined types are equal + BOOST_STATIC_ASSERT((detail::is_same<make_list_base_hook<void_pointer<void*>, link_mode<safe_link> >::type + ,make_list_base_hook<>::type + >::value)); + + BOOST_STATIC_ASSERT((detail::is_same<make_slist_base_hook<void_pointer<void*>, link_mode<safe_link> >::type + ,make_slist_base_hook<>::type + >::value)); + + BOOST_STATIC_ASSERT((detail::is_same<make_set_base_hook<void_pointer<void*>, link_mode<safe_link> >::type + ,make_set_base_hook<>::type + >::value)); + + BOOST_STATIC_ASSERT((detail::is_same<make_unordered_set_base_hook<void_pointer<void*>, link_mode<safe_link> >::type + ,make_unordered_set_base_hook<>::type + >::value)); + + BOOST_STATIC_ASSERT((detail::is_same<make_avl_set_base_hook<void_pointer<void*>, link_mode<safe_link> >::type + ,make_avl_set_base_hook<>::type + >::value)); + + BOOST_STATIC_ASSERT((detail::is_same<make_bs_set_base_hook<void_pointer<void*>, link_mode<safe_link> >::type + ,make_bs_set_base_hook<>::type + >::value)); + + //Check defined types and implicitly defined types are unequal + BOOST_STATIC_ASSERT(!(detail::is_same<make_list_base_hook<void_pointer<void*>, link_mode<normal_link> >::type + ,make_list_base_hook<>::type + >::value)); + + BOOST_STATIC_ASSERT(!(detail::is_same<make_slist_base_hook<void_pointer<void*>, link_mode<normal_link> >::type + ,make_slist_base_hook<>::type + >::value)); + + BOOST_STATIC_ASSERT(!(detail::is_same<make_set_base_hook<void_pointer<void*>, link_mode<normal_link> >::type + ,make_set_base_hook<>::type + >::value)); + + BOOST_STATIC_ASSERT(!(detail::is_same<make_unordered_set_base_hook<void_pointer<void*>, link_mode<normal_link> >::type + ,make_unordered_set_base_hook<>::type + >::value)); + + BOOST_STATIC_ASSERT(!(detail::is_same<make_avl_set_base_hook<void_pointer<void*>, link_mode<normal_link> >::type + ,make_avl_set_base_hook<>::type + >::value)); + + BOOST_STATIC_ASSERT(!(detail::is_same<make_bs_set_base_hook<void_pointer<void*>, link_mode<normal_link> >::type + ,make_bs_set_base_hook<>::type + >::value)); + + return 0; +} diff --git a/src/boost/libs/intrusive/test/multiset_test.cpp b/src/boost/libs/intrusive/test/multiset_test.cpp new file mode 100644 index 00000000..a8ab6743 --- /dev/null +++ b/src/boost/libs/intrusive/test/multiset_test.cpp @@ -0,0 +1,155 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (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 <boost/intrusive/set.hpp> +#include "itestvalue.hpp" +#include "bptr_value.hpp" +#include "smart_ptr.hpp" +#include "rb_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<ValueTraits, DefaultHolder, Map> common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef multiset + < typename common_t::value_type + , value_traits<ValueTraits> + , constant_time_size<ConstantTimeSize> + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value)); + }; +}; +enum HookType +{ + Base, + Member, + NonMember +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type> +class test_main_template; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base> +{ + public: + static void execute() + { + typedef testvalue_traits< rb_hooks<VoidPointer> > 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 + < rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member> +{ + public: + static void execute() + { + typedef testvalue_traits< rb_hooks<VoidPointer> > testval_traits_t; + //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 + < rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember> +{ + public: + static void execute() + { + typedef testvalue_traits< rb_hooks<VoidPointer> > testval_traits_t; + //nonmember + test::test_generic_multiset + < rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template < bool ConstantTimeSize, bool Map > +struct test_main_template_bptr +{ + static void execute() + { + typedef BPtr_Value_Traits< RBTree_BPtr_Node_Traits > value_traits; + typedef bounded_allocator< BPtr_Value > allocator_type; + + bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope; + test::test_generic_multiset + < 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<void*, false, false, false, Base>::execute(); + //test_main_template<void*, false, false, true>::execute(); + test_main_template<void*, false, true, false, Member>::execute(); + //test_main_template<void*, false, true, true>::execute(); + test_main_template<void*, true, false, false, Base>::execute(); + //test_main_template<void*, true, false, true>::execute(); + test_main_template<void*, true, true, false, Member>::execute(); + test_main_template<void*, true, true, true, NonMember>::execute(); + + //smart_ptr + //test_main_template<smart_ptr<void>, false, false, false>::execute(); + test_main_template<smart_ptr<void>, false, false, true, Base>::execute(); + //test_main_template<smart_ptr<void>, false, true, false>::execute(); + test_main_template<smart_ptr<void>, false, true, true, Member>::execute(); + //test_main_template<smart_ptr<void>, true, false, false>::execute(); + test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute(); + //test_main_template<smart_ptr<void>, true, true, false>::execute(); + //test_main_template<smart_ptr<void>, 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/src/boost/libs/intrusive/test/nonhook_node.hpp b/src/boost/libs/intrusive/test/nonhook_node.hpp new file mode 100644 index 00000000..e2c666e7 --- /dev/null +++ b/src/boost/libs/intrusive/test/nonhook_node.hpp @@ -0,0 +1,121 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Matei David 2014-2014. +// (C) Copyright Ion Gaztanaga 2014-2014. +// +// 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_NONHOOK_NODE_HPP +#define BOOST_INTRUSIVE_DETAIL_NONHOOK_NODE_HPP + +#include <boost/intrusive/detail/config_begin.hpp> +#include <boost/intrusive/pointer_traits.hpp> +#include <boost/intrusive/detail/parent_from_member.hpp> + +#include <boost/move/detail/to_raw_pointer.hpp> + +#include <boost/static_assert.hpp> +#include <boost/detail/lightweight_test.hpp> + +namespace boost{ +namespace intrusive{ + +//This node will only be used in safe or auto unlink modes +//so test it's been properly released +template < typename NodeTraits, template <typename> class Node_Algorithms > +struct nonhook_node_member : public NodeTraits::node +{ + typedef NodeTraits node_traits; + typedef typename node_traits::node node; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; + typedef Node_Algorithms< node_traits > node_algorithms; + + nonhook_node_member() + { + node_algorithms::init(pointer_traits<node_ptr>::pointer_to(static_cast< node& >(*this))); + } + + nonhook_node_member(const nonhook_node_member& rhs) + { + BOOST_TEST(!rhs.is_linked()); + node_algorithms::init(pointer_traits<node_ptr>::pointer_to(static_cast< node& >(*this))); + } + + nonhook_node_member& operator = (const nonhook_node_member& rhs) + { + BOOST_TEST(!this->is_linked() && !rhs.is_linked()); + return *this; + } + + ~nonhook_node_member() + { + BOOST_TEST(!this->is_linked()); + node_algorithms::init(pointer_traits<node_ptr>::pointer_to(static_cast< node& >(*this))); + } + + void swap_nodes(nonhook_node_member& other) + { + node_algorithms::swap_nodes(pointer_traits<node_ptr>::pointer_to(static_cast< node& >(*this)), + pointer_traits<node_ptr>::pointer_to(static_cast< node& >(other))); + } + + bool is_linked() const + { + return !node_algorithms::unique(pointer_traits<const_node_ptr>::pointer_to(static_cast< const node& >(*this))); + } +}; + +template < typename T, typename NonHook_Member, NonHook_Member T::* P, link_mode_type Link_Mode > +struct nonhook_node_member_value_traits +{ + typedef T value_type; + typedef typename NonHook_Member::node_traits node_traits; + typedef typename node_traits::node node; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; + typedef typename pointer_traits<node_ptr>:: + template rebind_pointer<T>::type pointer; + typedef typename pointer_traits<node_ptr>:: + template rebind_pointer<const T>::type const_pointer; + typedef T & reference; + typedef const T & const_reference; + + static const link_mode_type link_mode = Link_Mode; + + BOOST_STATIC_ASSERT((Link_Mode == safe_link || Link_Mode == auto_unlink)); + + static node_ptr to_node_ptr(reference value) + { + return pointer_traits<node_ptr>::pointer_to(static_cast<node&>(value.*P)); + } + + static const_node_ptr to_node_ptr(const_reference value) + { + return pointer_traits<const_node_ptr>::pointer_to(static_cast<const node&>(value.*P)); + } + + static pointer to_value_ptr(node_ptr n) + { + return pointer_traits<pointer>::pointer_to + (*detail::parent_from_member<T, NonHook_Member> + (static_cast<NonHook_Member*>(boost::movelib::to_raw_pointer(n)), P)); + } + + static const_pointer to_value_ptr(const_node_ptr n) + { + return pointer_traits<const_pointer>::pointer_to + (*detail::parent_from_member<T, NonHook_Member> + (static_cast<const NonHook_Member*>(boost::movelib::to_raw_pointer(n)), P)); + } +}; + +} +} + +#endif diff --git a/src/boost/libs/intrusive/test/null_iterator_test.cpp b/src/boost/libs/intrusive/test/null_iterator_test.cpp new file mode 100644 index 00000000..1905a656 --- /dev/null +++ b/src/boost/libs/intrusive/test/null_iterator_test.cpp @@ -0,0 +1,95 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014. 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/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include <boost/intrusive/list.hpp> +#include <boost/intrusive/slist.hpp> +#include <boost/intrusive/bs_set.hpp> +#include <boost/intrusive/set.hpp> +#include <boost/intrusive/avl_set.hpp> +#include <boost/intrusive/sg_set.hpp> +#include <boost/intrusive/treap_set.hpp> +#include <boost/intrusive/splay_set.hpp> +#include <boost/intrusive/detail/mpl.hpp> + +#include <boost/core/lightweight_test.hpp> +#include <boost/aligned_storage.hpp> +#include <boost/static_assert.hpp> +#include <cstring> +#include <new> + +using namespace boost::intrusive; + +struct Type + : list_base_hook<> + , slist_base_hook<> + , set_base_hook<> + , avl_set_base_hook<> + , bs_set_base_hook<> +{}; + +typedef boost::aligned_storage<sizeof(void*)*4>::type buffer_t; + +static buffer_t buffer_0x00; +static buffer_t buffer_0xFF; + +template<class Iterator> +const Iterator &on_0x00_buffer() +{ + BOOST_STATIC_ASSERT(sizeof(buffer_t) >= sizeof(Iterator)); + return * ::new(std::memset(&buffer_0x00, 0x00, sizeof(buffer_0x00))) Iterator(); +} + +template<class Iterator> +const Iterator &on_0xFF_buffer() +{ + BOOST_STATIC_ASSERT(sizeof(buffer_t) >= sizeof(Iterator)); + return * ::new(std::memset(&buffer_0xFF, 0xFF, sizeof(buffer_0xFF))) Iterator(); +} + +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reverse_iterator) +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_reverse_iterator) + + +template<class Container> +void check_null_iterators() +{ + typedef typename Container::iterator iterator; + typedef typename Container::const_iterator const_iterator; + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT + (::, Container + ,reverse_iterator, iterator) reverse_iterator; + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT + (::, Container + ,const_reverse_iterator, const_iterator) const_reverse_iterator; + + BOOST_TEST(on_0xFF_buffer<iterator>() == on_0x00_buffer<iterator>()); + BOOST_TEST(on_0xFF_buffer<const_iterator>() == on_0x00_buffer<const_iterator>()); + BOOST_TEST(on_0xFF_buffer<reverse_iterator>() == on_0x00_buffer<reverse_iterator>()); + BOOST_TEST(on_0xFF_buffer<const_reverse_iterator>() == on_0x00_buffer<const_reverse_iterator>()); +} + +int main() +{ + check_null_iterators< list<Type> >(); + check_null_iterators< slist<Type> >(); + check_null_iterators< bs_set<Type> >(); + check_null_iterators< set<Type> >(); + check_null_iterators< multiset<Type> >(); + check_null_iterators< avl_set<Type> >(); + check_null_iterators< avl_multiset<Type> >(); + check_null_iterators< sg_set<Type> >(); + check_null_iterators< sg_multiset<Type> >(); + check_null_iterators< treap_set<Type> >(); + check_null_iterators< treap_multiset<Type> >(); + check_null_iterators< splay_set<Type> >(); + check_null_iterators< splay_multiset<Type> >(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/intrusive/test/pack_options_test.cpp b/src/boost/libs/intrusive/test/pack_options_test.cpp new file mode 100644 index 00000000..2df1c0fe --- /dev/null +++ b/src/boost/libs/intrusive/test/pack_options_test.cpp @@ -0,0 +1,55 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2013-2013. 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 <boost/intrusive/pack_options.hpp> +#include <boost/intrusive/detail/mpl.hpp> +#include <boost/static_assert.hpp> + +struct empty_default{}; + +using namespace boost::intrusive; + +//Test BOOST_INTRUSIVE_OPTION_CONSTANT +BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, is_incremental) +const bool is_incremental_value = pack_options< empty_default, incremental<true> >::type::is_incremental; +BOOST_STATIC_ASSERT(( is_incremental_value == true )); + +//Test BOOST_INTRUSIVE_OPTION_TYPE +BOOST_INTRUSIVE_OPTION_TYPE(my_pointer, VoidPointer, typename boost::intrusive::detail::remove_pointer<VoidPointer>::type, my_pointer_type) +typedef pack_options< empty_default, my_pointer<void*> >::type::my_pointer_type my_pointer_type; +BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<my_pointer_type, void>::value )); + +//test combination of BOOST_INTRUSIVE_OPTION_CONSTANT and BOOST_INTRUSIVE_OPTION_TYPE +// First add new options +struct default_options +{ + static const long long_constant = -3; + typedef double * double_typedef; +}; + +BOOST_INTRUSIVE_OPTION_CONSTANT(incremental2, bool, Enabled, is_incremental2) +BOOST_INTRUSIVE_OPTION_TYPE(my_pointer2, VoidPointer, typename boost::intrusive::detail::add_pointer<VoidPointer>::type, my_pointer_type2) +typedef pack_options < default_options + , incremental<false> + , my_pointer<float*> + , incremental2<true> + , my_pointer2<const char*> + >::type combined_type; +BOOST_STATIC_ASSERT(( combined_type::is_incremental == false )); +BOOST_STATIC_ASSERT(( combined_type::is_incremental2 == true )); +BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<combined_type::my_pointer_type, float >::value )); +BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<combined_type::my_pointer_type2, const char**>::value )); + +//test packing the default options leads to a default options type +BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<pack_options<default_options>::type, default_options>::value )); + +int main() +{ + return 0; +} diff --git a/src/boost/libs/intrusive/test/parent_from_member_test.cpp b/src/boost/libs/intrusive/test/parent_from_member_test.cpp new file mode 100644 index 00000000..3fbc01f3 --- /dev/null +++ b/src/boost/libs/intrusive/test/parent_from_member_test.cpp @@ -0,0 +1,172 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014 +// +// 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 <boost/intrusive/parent_from_member.hpp> +#include <boost/core/lightweight_test.hpp> + +struct POD +{ + int int_; + float float_; +}pod; + +struct Derived + : public POD +{ + int derived_int_; + float derived_float_; +}derived; + +struct Abstract +{ + int abstract_int_; + float abstract_float_; + virtual void virtual_func1() = 0; + virtual void virtual_func2() = 0; + virtual ~Abstract(){} +}; + +struct DerivedPoly + : public Abstract +{ + int derivedpoly_int_; + float derivedpoly_float_; + virtual void virtual_func1(){} + virtual void virtual_func2(){} + Abstract *abstract() { return this; } + Abstract const *abstract() const { return this; } +} derivedpoly; + +struct MultiInheritance + : public Derived, public DerivedPoly +{ + int multiinheritance_int_; + float multiinheritance_float_; +} multiinheritance; + +struct Abstract2 +{ + int abstract2_int_; + float abstract2_float_; + virtual void virtual_func1() = 0; + virtual void virtual_func2() = 0; + virtual ~Abstract2(){} +}; + +struct DerivedPoly2 + : public Abstract2 +{ + int derivedpoly2_int_; + float derivedpoly2_float_; + virtual void virtual_func1(){} + virtual void virtual_func2(){} + Abstract2 *abstract2() { return this; } + Abstract2 const *abstract2() const { return this; } + virtual ~DerivedPoly2(){} +} derivedpoly2; + +struct MultiInheritance2 + : public DerivedPoly, public DerivedPoly2 +{ + int multiinheritance2_int_; + float multiinheritance2_float_; +} multiinheritance2; + +struct VirtualDerivedPoly + : public virtual Derived +{ + int virtualderivedpoly_int_; + float virtualderivedpoly_float_; + virtual void f1(){} + virtual void f2(){} + virtual ~VirtualDerivedPoly(){} +} virtualderivedpoly; + +struct VirtualMultipleDerivedPoly + : public virtual Derived, virtual public DerivedPoly +{ + int virtualmultiplederivedpoly_int_; + float virtualmultiplederivedpoly_float_; + virtual void f1(){} + virtual void f2(){} + virtual ~VirtualMultipleDerivedPoly(){} +} virtualmultiplederivedpoly; + +struct VirtualDerived + : public virtual Derived +{ + int virtualderived_int_; + float virtualderived_float_; + virtual void f1(){} + virtual void f2(){} + virtual ~VirtualDerived(){} +} virtualderived; + +using namespace boost::intrusive; + +//Add new test with https://svn.boost.org/trac/boost/attachment/ticket/8512/Source1.cpp + +int main() +{ + //POD + BOOST_TEST(&pod == get_parent_from_member(&pod.int_, &POD::int_)); + BOOST_TEST(&pod == get_parent_from_member(&pod.float_, &POD::float_)); + + //Derived + BOOST_TEST(&derived == get_parent_from_member(&derived.int_, &Derived::int_)); + BOOST_TEST(&derived == get_parent_from_member(&derived.float_, &Derived::float_)); + BOOST_TEST(&derived == get_parent_from_member(&derived.derived_int_, &Derived::derived_int_)); + BOOST_TEST(&derived == get_parent_from_member(&derived.derived_float_, &Derived::derived_float_)); + + //Abstract + BOOST_TEST(derivedpoly.abstract() == get_parent_from_member(&derivedpoly.abstract_int_, &Abstract::abstract_int_)); + BOOST_TEST(derivedpoly.abstract() == get_parent_from_member(&derivedpoly.abstract_float_, &Abstract::abstract_float_)); + + //DerivedPoly + BOOST_TEST(&derivedpoly == get_parent_from_member(&derivedpoly.abstract_int_, &DerivedPoly::abstract_int_)); + BOOST_TEST(&derivedpoly == get_parent_from_member(&derivedpoly.abstract_float_, &DerivedPoly::abstract_float_)); + BOOST_TEST(&derivedpoly == get_parent_from_member(&derivedpoly.derivedpoly_int_, &DerivedPoly::derivedpoly_int_)); + BOOST_TEST(&derivedpoly == get_parent_from_member(&derivedpoly.derivedpoly_float_, &DerivedPoly::derivedpoly_float_)); + + //MultiInheritance + BOOST_TEST(multiinheritance.abstract() == get_parent_from_member(&multiinheritance.abstract_int_, &MultiInheritance::abstract_int_)); + BOOST_TEST(multiinheritance.abstract() == get_parent_from_member(&multiinheritance.abstract_float_, &MultiInheritance::abstract_float_)); + BOOST_TEST(&multiinheritance == get_parent_from_member(&multiinheritance.derivedpoly_int_, &MultiInheritance::derivedpoly_int_)); + BOOST_TEST(&multiinheritance == get_parent_from_member(&multiinheritance.derivedpoly_float_, &MultiInheritance::derivedpoly_float_)); + BOOST_TEST(&multiinheritance == get_parent_from_member(&multiinheritance.int_, &MultiInheritance::int_)); + BOOST_TEST(&multiinheritance == get_parent_from_member(&multiinheritance.float_, &MultiInheritance::float_)); + BOOST_TEST(&multiinheritance == get_parent_from_member(&multiinheritance.derived_int_, &MultiInheritance::derived_int_)); + BOOST_TEST(&multiinheritance == get_parent_from_member(&multiinheritance.derived_float_, &MultiInheritance::derived_float_)); + + BOOST_TEST(multiinheritance.abstract() == get_parent_from_member(&multiinheritance.abstract_int_, &MultiInheritance::abstract_int_)); + BOOST_TEST(multiinheritance.abstract() == get_parent_from_member(&multiinheritance.abstract_float_, &MultiInheritance::abstract_float_)); + BOOST_TEST(&multiinheritance == get_parent_from_member(&multiinheritance.derivedpoly_int_, &MultiInheritance::derivedpoly_int_)); + BOOST_TEST(&multiinheritance == get_parent_from_member(&multiinheritance.derivedpoly_float_, &MultiInheritance::derivedpoly_float_)); + BOOST_TEST(multiinheritance2.abstract2() == get_parent_from_member(&multiinheritance2.abstract2_int_, &MultiInheritance2::abstract2_int_)); + BOOST_TEST(multiinheritance2.abstract2() == get_parent_from_member(&multiinheritance2.abstract2_float_, &MultiInheritance2::abstract2_float_)); + BOOST_TEST(&multiinheritance2 == get_parent_from_member(&multiinheritance2.derivedpoly2_int_, &MultiInheritance2::derivedpoly2_int_)); + BOOST_TEST(&multiinheritance2 == get_parent_from_member(&multiinheritance2.derivedpoly2_float_, &MultiInheritance2::derivedpoly2_float_)); + + //MSVC pointer to member data uses RTTI info even when not crossing virtual base boundaries + #ifndef BOOST_INTRUSIVE_MSVC_ABI_PTR_TO_MEMBER + BOOST_TEST(&virtualderived == get_parent_from_member(&virtualderived.virtualderived_int_, &VirtualDerived::virtualderived_int_)); + BOOST_TEST(&virtualderived == get_parent_from_member(&virtualderived.virtualderived_float_, &VirtualDerived::virtualderived_float_)); + + BOOST_TEST(&virtualderivedpoly == get_parent_from_member(&virtualderivedpoly.virtualderivedpoly_int_, &VirtualDerivedPoly::virtualderivedpoly_int_)); + BOOST_TEST(&virtualderivedpoly == get_parent_from_member(&virtualderivedpoly.virtualderivedpoly_float_, &VirtualDerivedPoly::virtualderivedpoly_float_)); + BOOST_TEST(&virtualmultiplederivedpoly == get_parent_from_member(&virtualmultiplederivedpoly.virtualmultiplederivedpoly_float_, &VirtualMultipleDerivedPoly::virtualmultiplederivedpoly_float_)); + BOOST_TEST(&virtualmultiplederivedpoly == get_parent_from_member(&virtualmultiplederivedpoly.virtualmultiplederivedpoly_int_, &VirtualMultipleDerivedPoly::virtualmultiplederivedpoly_int_)); + BOOST_TEST(&virtualmultiplederivedpoly == get_parent_from_member(&virtualmultiplederivedpoly.derivedpoly_float_, &VirtualMultipleDerivedPoly::derivedpoly_float_)); + BOOST_TEST(&virtualmultiplederivedpoly == get_parent_from_member(&virtualmultiplederivedpoly.derivedpoly_int_, &VirtualMultipleDerivedPoly::derivedpoly_int_)); + #endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/intrusive/test/pointer_traits_test.cpp b/src/boost/libs/intrusive/test/pointer_traits_test.cpp new file mode 100644 index 00000000..73ea4f8c --- /dev/null +++ b/src/boost/libs/intrusive/test/pointer_traits_test.cpp @@ -0,0 +1,223 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2013. 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 <boost/intrusive/detail/mpl.hpp> +#include <boost/static_assert.hpp> +#include <boost/intrusive/pointer_traits.hpp> +#include <boost/core/lightweight_test.hpp> + +struct CompleteSmartPtrStats +{ + static unsigned static_cast_called; + static unsigned dynamic_cast_called; + static unsigned const_cast_called; + static unsigned pointer_to_called; + + static void reset_stats() + { + static_cast_called = 0; + dynamic_cast_called = 0; + const_cast_called = 0; + pointer_to_called = 0; + } +}; + +unsigned CompleteSmartPtrStats::static_cast_called= 0; +unsigned CompleteSmartPtrStats::dynamic_cast_called = 0; +unsigned CompleteSmartPtrStats::const_cast_called = 0; +unsigned CompleteSmartPtrStats::pointer_to_called = 0; + +template<class T> +class CompleteSmartPtr +{ + template <class U> + friend class CompleteSmartPtr; + void unspecified_bool_type_func() const {} + typedef void (CompleteSmartPtr::*unspecified_bool_type)() const; + + public: + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + template <class U> using rebind = CompleteSmartPtr<U>; + #else + template <class U> struct rebind + { typedef CompleteSmartPtr<U> other; }; + #endif + + typedef char difference_type; + typedef T element_type; + + CompleteSmartPtr() + : ptr_(0) + {} + + explicit CompleteSmartPtr(T &p) + : ptr_(&p) + {} + + CompleteSmartPtr(const CompleteSmartPtr &c) + { this->ptr_ = c.ptr_; } + + CompleteSmartPtr & operator=(const CompleteSmartPtr &c) + { this->ptr_ = c.ptr_; } + + static CompleteSmartPtr pointer_to(T &r) + { ++CompleteSmartPtrStats::pointer_to_called; return CompleteSmartPtr(r); } + + T * operator->() const + { return ptr_; } + + T & operator *() const + { return *ptr_; } + + operator unspecified_bool_type() const + { return ptr_? &CompleteSmartPtr::unspecified_bool_type_func : 0; } + + template<class U> + static CompleteSmartPtr static_cast_from(const CompleteSmartPtr<U> &uptr) + { + ++CompleteSmartPtrStats::static_cast_called; + element_type* const p = static_cast<element_type*>(uptr.ptr_); + return p ? CompleteSmartPtr(*p) : CompleteSmartPtr(); + } + + template<class U> + static CompleteSmartPtr const_cast_from(const CompleteSmartPtr<U> &uptr) + { + ++CompleteSmartPtrStats::const_cast_called; + element_type* const p = const_cast<element_type*>(uptr.ptr_); + return p ? CompleteSmartPtr(*p) : CompleteSmartPtr(); + } + + template<class U> + static CompleteSmartPtr dynamic_cast_from(const CompleteSmartPtr<U> &uptr) + { + ++CompleteSmartPtrStats::dynamic_cast_called; + element_type* const p = dynamic_cast<element_type*>(uptr.ptr_); + return p ? CompleteSmartPtr(*p) : CompleteSmartPtr(); + } + + friend bool operator ==(const CompleteSmartPtr &l, const CompleteSmartPtr &r) + { return l.ptr_ == r.ptr_; } + + friend bool operator !=(const CompleteSmartPtr &l, const CompleteSmartPtr &r) + { return l.ptr_ != r.ptr_; } + + private: + T *ptr_; +}; + + +template<class T> +class SimpleSmartPtr +{ + void unspecified_bool_type_func() const {} + typedef void (SimpleSmartPtr::*unspecified_bool_type)() const; + public: + + SimpleSmartPtr() + : ptr_(0) + {} + + explicit SimpleSmartPtr(T *p) + : ptr_(p) + {} + + SimpleSmartPtr(const SimpleSmartPtr &c) + { this->ptr_ = c.ptr_; } + + SimpleSmartPtr & operator=(const SimpleSmartPtr &c) + { this->ptr_ = c.ptr_; } + + friend bool operator ==(const SimpleSmartPtr &l, const SimpleSmartPtr &r) + { return l.ptr_ == r.ptr_; } + + friend bool operator !=(const SimpleSmartPtr &l, const SimpleSmartPtr &r) + { return l.ptr_ != r.ptr_; } + + T* operator->() const + { return ptr_; } + + T & operator *() const + { return *ptr_; } + + operator unspecified_bool_type() const + { return ptr_? &SimpleSmartPtr::unspecified_bool_type_func : 0; } + + private: + T *ptr_; +}; + +class B{ public: virtual ~B(){} }; +class D : public B {}; +class DD : public virtual B {}; + +int main() +{ + int dummy; + + //Raw pointer + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits + <int*>::element_type, int>::value )); + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits + <int*>::pointer, int*>::value )); + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits + <int*>::difference_type, std::ptrdiff_t>::value )); + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits + <int*>::rebind_pointer<double>::type + , double*>::value )); + BOOST_TEST(boost::intrusive::pointer_traits<int*>::pointer_to(dummy) == &dummy); + BOOST_TEST(boost::intrusive::pointer_traits<D*>:: static_cast_from((B*)0) == 0); + BOOST_TEST(boost::intrusive::pointer_traits<D*>:: const_cast_from((const D*)0) == 0); + BOOST_TEST(boost::intrusive::pointer_traits<DD*>:: dynamic_cast_from((B*)0) == 0); + + //Complete smart pointer + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits + < CompleteSmartPtr<int> >::element_type, int>::value )); + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits + < CompleteSmartPtr<int> >::pointer, CompleteSmartPtr<int> >::value )); + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits + < CompleteSmartPtr<int> >::difference_type, char>::value )); + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits + < CompleteSmartPtr<int> >::rebind_pointer<double>::type + , CompleteSmartPtr<double> >::value )); + //pointer_to + CompleteSmartPtrStats::reset_stats(); + BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr<int> >::pointer_to(dummy) == CompleteSmartPtr<int>(dummy)); + BOOST_TEST(CompleteSmartPtrStats::pointer_to_called == 1); + //static_cast_from + CompleteSmartPtrStats::reset_stats(); + BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr<D> >::static_cast_from(CompleteSmartPtr<B>()) == CompleteSmartPtr<D>()); + BOOST_TEST(CompleteSmartPtrStats::static_cast_called == 1); + //const_cast_from + CompleteSmartPtrStats::reset_stats(); + BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr<D> >::const_cast_from(CompleteSmartPtr<const D>()) == CompleteSmartPtr<D>()); + BOOST_TEST(CompleteSmartPtrStats::const_cast_called == 1); + //dynamic_cast_from + CompleteSmartPtrStats::reset_stats(); + BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr<DD> >::dynamic_cast_from(CompleteSmartPtr<B>()) == CompleteSmartPtr<DD>()); + BOOST_TEST(CompleteSmartPtrStats::dynamic_cast_called == 1); + + //Simple smart pointer + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits + < SimpleSmartPtr<int> >::element_type, int>::value )); + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits + < SimpleSmartPtr<int> >::pointer, SimpleSmartPtr<int> >::value )); + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits + < SimpleSmartPtr<int> >::difference_type, std::ptrdiff_t>::value )); + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits + < SimpleSmartPtr<int> >::rebind_pointer<double>::type + , SimpleSmartPtr<double> >::value )); + + BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr<int> >::pointer_to(dummy) == SimpleSmartPtr<int>(&dummy)); + BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr<D> > ::static_cast_from(SimpleSmartPtr<B>()) == SimpleSmartPtr<D>()); + BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr<D> > ::const_cast_from(SimpleSmartPtr<const D>()) == SimpleSmartPtr<D>()); + BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr<DD> >::dynamic_cast_from(SimpleSmartPtr<B>()) == SimpleSmartPtr<DD>()); + + return boost::report_errors(); +} diff --git a/src/boost/libs/intrusive/test/rb_test_common.hpp b/src/boost/libs/intrusive/test/rb_test_common.hpp new file mode 100644 index 00000000..f9aa5123 --- /dev/null +++ b/src/boost/libs/intrusive/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 <boost/intrusive/set_hook.hpp> +#include <boost/intrusive/detail/mpl.hpp> +#include "bs_test_common.hpp" + +namespace boost { +namespace intrusive { + +template<class VoidPointer> +struct rb_hooks +{ + typedef set_base_hook<void_pointer<VoidPointer> > base_hook_type; + typedef set_base_hook + <link_mode<auto_unlink> + , void_pointer<VoidPointer> + , tag<void> + , optimize_size<true> > auto_base_hook_type; + typedef set_member_hook + <void_pointer<VoidPointer> + , optimize_size<true> > member_hook_type; + typedef set_member_hook + < link_mode<auto_unlink> + , void_pointer<VoidPointer> > auto_member_hook_type; + typedef nonhook_node_member< rbtree_node_traits<VoidPointer>, + rbtree_algorithms + > nonhook_node_member_type; +}; + +} //namespace intrusive { +} //namespace boost { + +#endif //BOOST_INTRUSIVE_TEST_RB_TEST_COMMON_HPP diff --git a/src/boost/libs/intrusive/test/recursive_test.cpp b/src/boost/libs/intrusive/test/recursive_test.cpp new file mode 100644 index 00000000..a6fe73a2 --- /dev/null +++ b/src/boost/libs/intrusive/test/recursive_test.cpp @@ -0,0 +1,71 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2013 +// +// 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 <boost/intrusive/list.hpp> +#include <boost/intrusive/slist.hpp> +#include <boost/intrusive/set.hpp> +#include <boost/intrusive/unordered_set.hpp> +#include <boost/intrusive/avl_set.hpp> +#include <boost/intrusive/sg_set.hpp> +#include <boost/intrusive/splay_set.hpp> +#include <boost/intrusive/treap_set.hpp> +#include <cassert> + +using namespace boost::intrusive; + +typedef list_base_hook<> ListBaseHook; +typedef slist_base_hook<> SListBaseHook; +typedef set_base_hook<> SetBaseHook; +typedef unordered_set_base_hook<> USetBaseHook; + +class Foo; +typedef unordered_set<Foo, base_hook<USetBaseHook> > USet; + +class Foo : public ListBaseHook, public SListBaseHook, public SetBaseHook, public USetBaseHook +{ + USet::bucket_type buckets[1]; + Foo(const Foo &); + Foo & operator=(const Foo &); + + public: + Foo() : uset_children(USet::bucket_traits(buckets, 1)) + {} + list <Foo, base_hook<ListBaseHook> > list_children; + slist<Foo, base_hook<SListBaseHook> > slist_children; + set <Foo, base_hook<SetBaseHook> > set_children; + USet uset_children; +}; + +void instantiate() +{ + list< Foo, base_hook<ListBaseHook> > list_; list_.clear(); + slist< Foo, base_hook<SListBaseHook> > slist_; slist_.clear(); + set< Foo, base_hook<SetBaseHook> > set_; set_.clear(); + + USet::bucket_type buckets[1]; + USet unordered_set_(USet::bucket_traits(buckets, 1)); unordered_set_.clear(); +} +int main() +{ + instantiate(); + + //A small test with list + { + Foo f, f2; + list< Foo, base_hook<ListBaseHook> > l; + l.insert(l.begin(), f); + l.begin()->list_children.insert(l.begin()->list_children.begin(), f2); + assert(l.size() == l.begin()->list_children.size()); + l.begin()->list_children.clear(); + l.clear(); + } + return 0; +} diff --git a/src/boost/libs/intrusive/test/scary_iterators_test.cpp b/src/boost/libs/intrusive/test/scary_iterators_test.cpp new file mode 100644 index 00000000..6c4b4269 --- /dev/null +++ b/src/boost/libs/intrusive/test/scary_iterators_test.cpp @@ -0,0 +1,314 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2013-2013 +// +// 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 <boost/intrusive/list.hpp> +#include <boost/intrusive/slist.hpp> +#include <boost/intrusive/set.hpp> +#include <boost/intrusive/unordered_set.hpp> +#include <boost/intrusive/avl_set.hpp> +#include <boost/intrusive/sg_set.hpp> +#include <boost/intrusive/bs_set.hpp> +#include <boost/intrusive/splay_set.hpp> +#include <boost/intrusive/treap_set.hpp> +#include <boost/intrusive/detail/mpl.hpp> +#include <boost/static_assert.hpp> +#include "smart_ptr.hpp" +#include <functional> //std::greater/std::less + +using namespace boost::intrusive; +struct my_tag; + +template<class VoidPtr = void*, link_mode_type mode = normal_link> +class MyClass +: public make_list_base_hook + < void_pointer<VoidPtr>, link_mode<mode> >::type +, public make_slist_base_hook + < void_pointer<VoidPtr>, link_mode<mode> >::type +, public make_set_base_hook + < void_pointer<VoidPtr>, link_mode<mode> >::type +, public make_unordered_set_base_hook + < void_pointer<VoidPtr>, link_mode<mode> >::type +, public make_avl_set_base_hook + < void_pointer<VoidPtr>, link_mode<mode> >::type +, public make_bs_set_base_hook + < void_pointer<VoidPtr>, link_mode<mode> >::type +{ + int int_; + + public: + MyClass(int i) + : int_(i) + {} + + friend bool operator<(const MyClass &l, const MyClass &r) + { return l.int_ < r.int_; } + + friend bool operator==(const MyClass &l, const MyClass &r) + { return l.int_ == r.int_; } + + friend std::size_t hash_value(const MyClass &v) + { return boost::hash_value(v.int_); } + + friend bool priority_order(const MyClass &l, const MyClass &r) + { return l.int_ < r.int_; } +}; + +template<class T> +struct inverse_priority +{ + bool operator()(const T &l, const T &r) + { return l.int_ > r.int_; } +}; + +template<class T> +struct inverse_hash +{ + bool operator()(const T &l) + { return hash_value(l); } +}; + +template<class T> +struct alternative_equal +{ + bool operator()(const T &l, const T &r) + { return l.int_ == r.int_; } +}; + +int main() +{ + //////////// + // list + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< list<MyClass<> >::iterator + , list<MyClass<> >::const_iterator + >::value)); + //constant_time_size does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< list<MyClass<>, constant_time_size<true> >::iterator + , list<MyClass<>, constant_time_size<false> >::iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< list<MyClass<> >::iterator + , list<MyClass<smart_ptr<void> > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< list<MyClass<>, size_type<unsigned int > >::iterator + , list<MyClass<>, size_type<unsigned char> >::iterator + >::value)); + //////////// + // slist + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< slist<MyClass<> >::iterator + , slist<MyClass<> >::const_iterator + >::value)); + //constant_time_size does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< slist<MyClass<>, constant_time_size<true> >::iterator + , slist<MyClass<>, constant_time_size<false> >::iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< slist<MyClass<> >::iterator + , slist<MyClass<smart_ptr<void> > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< slist<MyClass<>, size_type<unsigned int > >::iterator + , slist<MyClass<>, size_type<unsigned char> >::iterator + >::value)); + //cache_last does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< slist<MyClass<>, cache_last<false> >::iterator + , slist<MyClass<>, cache_last<true> >::iterator + >::value)); + //linear does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< slist<MyClass<>, linear<false> >::iterator + , slist<MyClass<>, linear<true> >::iterator + >::value)); + //////////// + // set + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< set<MyClass<> >::iterator + , set<MyClass<> >::const_iterator + >::value)); + //constant_time_size does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< set<MyClass<>, constant_time_size<true> >::iterator + , set<MyClass<>, constant_time_size<false> >::iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< set<MyClass<> >::iterator + , set<MyClass<smart_ptr<void> > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< set<MyClass<>, size_type<unsigned int > >::iterator + , set<MyClass<>, size_type<unsigned char> >::iterator + >::value)); + //compare does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< set<MyClass<>, compare< std::greater<MyClass<> > > >::iterator + , set<MyClass<>, compare< std::less<MyClass<> > > >::iterator + >::value)); + //////////// + // avl_set + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< avl_set<MyClass<> >::iterator + , avl_set<MyClass<> >::const_iterator + >::value)); + //constant_time_size does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< avl_set<MyClass<>, constant_time_size<true> >::iterator + , avl_set<MyClass<>, constant_time_size<false> >::iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< avl_set<MyClass<> >::iterator + , avl_set<MyClass<smart_ptr<void> > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< avl_set<MyClass<>, size_type<unsigned int > >::iterator + , avl_set<MyClass<>, size_type<unsigned char> >::iterator + >::value)); + //compare does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< avl_set<MyClass<>, compare< std::greater<MyClass<> > > >::iterator + , avl_set<MyClass<>, compare< std::less<MyClass<> > > >::iterator + >::value)); + //////////// + // sg_set + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< sg_set<MyClass<> >::iterator + , sg_set<MyClass<> >::const_iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< sg_set<MyClass<> >::iterator + , sg_set<MyClass<smart_ptr<void> > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< sg_set<MyClass<>, size_type<unsigned int > >::iterator + , sg_set<MyClass<>, size_type<unsigned char> >::iterator + >::value)); + //compare does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< sg_set<MyClass<>, compare< std::greater<MyClass<> > > >::iterator + , sg_set<MyClass<>, compare< std::less<MyClass<> > > >::iterator + >::value)); + //floating_point does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< sg_set<MyClass<>, floating_point<false> >::iterator + , sg_set<MyClass<>, floating_point<true> >::iterator + >::value)); + //////////// + // bs_set + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< bs_set<MyClass<> >::iterator + , bs_set<MyClass<> >::const_iterator + >::value)); + //constant_time_size does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< bs_set<MyClass<>, constant_time_size<true> >::iterator + , bs_set<MyClass<>, constant_time_size<false> >::iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< bs_set<MyClass<> >::iterator + , bs_set<MyClass<smart_ptr<void> > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< bs_set<MyClass<>, size_type<unsigned int > >::iterator + , bs_set<MyClass<>, size_type<unsigned char> >::iterator + >::value)); + //compare does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< bs_set<MyClass<>, compare< std::greater<MyClass<> > > >::iterator + , bs_set<MyClass<>, compare< std::less<MyClass<> > > >::iterator + >::value)); + //////////// + // splay_set + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< splay_set<MyClass<> >::iterator + , splay_set<MyClass<> >::const_iterator + >::value)); + //constant_time_size does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< splay_set<MyClass<>, constant_time_size<true> >::iterator + , splay_set<MyClass<>, constant_time_size<false> >::iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< splay_set<MyClass<> >::iterator + , splay_set<MyClass<smart_ptr<void> > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< splay_set<MyClass<>, size_type<unsigned int > >::iterator + , splay_set<MyClass<>, size_type<unsigned char> >::iterator + >::value)); + //compare does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< splay_set<MyClass<>, compare< std::greater<MyClass<> > > >::iterator + , splay_set<MyClass<>, compare< std::less<MyClass<> > > >::iterator + >::value)); + //////////// + // treap_set + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< treap_set<MyClass<> >::iterator + , treap_set<MyClass<> >::const_iterator + >::value)); + //constant_time_size does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< treap_set<MyClass<>, constant_time_size<true> >::iterator + , treap_set<MyClass<>, constant_time_size<false> >::iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< treap_set<MyClass<> >::iterator + , treap_set<MyClass<smart_ptr<void> > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< treap_set<MyClass<>, size_type<unsigned int > >::iterator + , treap_set<MyClass<>, size_type<unsigned char> >::iterator + >::value)); + //compare does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< treap_set<MyClass<>, compare< std::greater<MyClass<> > > >::iterator + , treap_set<MyClass<>, compare< std::less<MyClass<> > > >::iterator + >::value)); + //priority does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< treap_set<MyClass<> >::iterator + , treap_set<MyClass<>, priority< inverse_priority<MyClass<> > > >::iterator + >::value)); + ////////////// + // common tree + ////////////// + BOOST_STATIC_ASSERT((detail::is_same< bs_set<MyClass<> >::iterator + , sg_set<MyClass<> >::iterator + >::value)); + BOOST_STATIC_ASSERT((detail::is_same< bs_set<MyClass<> >::iterator + , treap_set<MyClass<> >::iterator + >::value)); + BOOST_STATIC_ASSERT((detail::is_same< bs_set<MyClass<> >::iterator + , splay_set<MyClass<> >::iterator + >::value)); + //////////// + // unordered_set + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< unordered_set<MyClass<> >::iterator + , unordered_set<MyClass<> >::const_iterator + >::value)); + //constant_time_size does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< unordered_set<MyClass<>, constant_time_size<true> >::iterator + , unordered_set<MyClass<>, constant_time_size<false> >::iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< unordered_set<MyClass<> >::iterator + , unordered_set<MyClass<smart_ptr<void> > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< unordered_set<MyClass<>, size_type<unsigned int > >::iterator + , unordered_set<MyClass<>, size_type<unsigned char> >::iterator + >::value)); + //hash does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< unordered_set<MyClass<> >::iterator + , unordered_set<MyClass<>, hash< inverse_hash<MyClass<> > > >::iterator + >::value)); + //equal does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< unordered_set<MyClass<> >::iterator + , unordered_set<MyClass<>, equal< alternative_equal<MyClass<> > > >::iterator + >::value)); + //power_2_buckets does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< unordered_set<MyClass<> >::iterator + , unordered_set<MyClass<>, power_2_buckets<true> >::iterator + >::value)); + //cache_begin does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< unordered_set<MyClass<> >::iterator + , unordered_set<MyClass<>, cache_begin<true> >::iterator + >::value)); + return 0; +} diff --git a/src/boost/libs/intrusive/test/set_test.cpp b/src/boost/libs/intrusive/test/set_test.cpp new file mode 100644 index 00000000..e72575be --- /dev/null +++ b/src/boost/libs/intrusive/test/set_test.cpp @@ -0,0 +1,156 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (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 <boost/intrusive/set.hpp> +#include "itestvalue.hpp" +#include "bptr_value.hpp" +#include "smart_ptr.hpp" +#include "rb_test_common.hpp" +#include "generic_set_test.hpp" + +using namespace boost::intrusive; + +template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map > +struct rebinder +{ + typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef set + < typename common_t::value_type + , value_traits<ValueTraits> + , constant_time_size<ConstantTimeSize> + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value)); + }; +}; + +enum HookType +{ + Base, + Member, + NonMember +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type> +class test_main_template; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base> +{ + public: + static void execute() + { + typedef testvalue_traits< rb_hooks<VoidPointer> > 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 + < rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member> +{ + public: + static void execute() + { + typedef testvalue_traits< rb_hooks<VoidPointer> > testval_traits_t; + //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 + < rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember> +{ + public: + static void execute() + { + typedef testvalue_traits< rb_hooks<VoidPointer> > testval_traits_t; + //nonmember + test::test_generic_set + < rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template < bool ConstantTimeSize, bool Map > +struct test_main_template_bptr +{ + static void execute() + { + typedef BPtr_Value_Traits< RBTree_BPtr_Node_Traits > value_traits; + typedef bounded_allocator< BPtr_Value > allocator_type; + + bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope; + test::test_generic_set + < 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<void*, false, false, false, Base>::execute(); + //test_main_template<void*, false, false, true>::execute(); + test_main_template<void*, false, true, false, Member>::execute(); + //test_main_template<void*, false, true, true>::execute(); + test_main_template<void*, true, false, false, Base>::execute(); + //test_main_template<void*, true, false, true>::execute(); + test_main_template<void*, true, true, false, Member>::execute(); + test_main_template<void*, true, true, true, NonMember>::execute(); + + //smart_ptr + //test_main_template<smart_ptr<void>, false, false, false>::execute(); + test_main_template<smart_ptr<void>, false, false, true, Base>::execute(); + //test_main_template<smart_ptr<void>, false, true, false>::execute(); + test_main_template<smart_ptr<void>, false, true, true, Member>::execute(); + //test_main_template<smart_ptr<void>, true, false, false>::execute(); + test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute(); + //test_main_template<smart_ptr<void>, true, true, false>::execute(); + //test_main_template<smart_ptr<void>, 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/src/boost/libs/intrusive/test/sg_multiset_test.cpp b/src/boost/libs/intrusive/test/sg_multiset_test.cpp new file mode 100644 index 00000000..2a71cace --- /dev/null +++ b/src/boost/libs/intrusive/test/sg_multiset_test.cpp @@ -0,0 +1,148 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2013 +// +// 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 <boost/intrusive/sg_set.hpp> +#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 FloatingPoint, bool DefaultHolder, bool Map > +struct rebinder +{ + typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef sg_multiset + < typename common_t::value_type + , value_traits<ValueTraits> + , floating_point<FloatingPoint> + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value)); + }; +}; + +enum HookType +{ + Base, + Member, + NonMember +}; + +template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map, HookType Type> +class test_main_template; + +template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, FloatingPoint, DefaultHolder, Map, Base> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //base + typedef typename testval_traits_t::base_value_traits base_hook_t; + test::test_generic_multiset + < rebinder<base_hook_t, FloatingPoint, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, FloatingPoint, DefaultHolder, Map, Member> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //member + typedef typename testval_traits_t::member_value_traits member_hook_t; + test::test_generic_multiset + < rebinder<member_hook_t, FloatingPoint, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, FloatingPoint, DefaultHolder, Map, NonMember> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //nonmember + test::test_generic_multiset + < rebinder<typename testval_traits_t::nonhook_value_traits, FloatingPoint, DefaultHolder, Map> + >::test_all(); + } +}; + + +template < bool FloatingPoint, 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<allocator_type> bounded_scope; (void)bounded_scope; + test::test_generic_multiset + < rebinder< value_traits, FloatingPoint, true, Map> + >::test_all(); + } +}; + +int main() +{ + //Combinations: VoidPointer x FloatingPoint 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<void*, false, false, false, Base>::execute(); + //test_main_template<void*, false, false, true>::execute(); + test_main_template<void*, false, true, false, Member>::execute(); + //test_main_template<void*, false, true, true>::execute(); + test_main_template<void*, true, false, false, Base>::execute(); + //test_main_template<void*, true, false, true>::execute(); + test_main_template<void*, true, true, false, Member>::execute(); + test_main_template<void*, true, true, true, NonMember>::execute(); + + //smart_ptr + //test_main_template<smart_ptr<void>, false, false, false>::execute(); + test_main_template<smart_ptr<void>, false, false, true, Base>::execute(); + //test_main_template<smart_ptr<void>, false, true, false>::execute(); + test_main_template<smart_ptr<void>, false, true, true, Member>::execute(); + //test_main_template<smart_ptr<void>, true, false, false>::execute(); + test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute(); + //test_main_template<smart_ptr<void>, true, true, false>::execute(); + //test_main_template<smart_ptr<void>, true, true, true>::execute(); + + //bounded_ptr (bool FloatingPoint, 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/src/boost/libs/intrusive/test/sg_set_test.cpp b/src/boost/libs/intrusive/test/sg_set_test.cpp new file mode 100644 index 00000000..a115844f --- /dev/null +++ b/src/boost/libs/intrusive/test/sg_set_test.cpp @@ -0,0 +1,147 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2013 +// +// 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 <boost/intrusive/sg_set.hpp> +#include "itestvalue.hpp" +#include "bptr_value.hpp" +#include "smart_ptr.hpp" +#include "bs_test_common.hpp" +#include "generic_set_test.hpp" + +using namespace boost::intrusive; + +template < class ValueTraits, bool FloatingPoint, bool DefaultHolder, bool Map > +struct rebinder +{ + typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef sg_set + < typename common_t::value_type + , value_traits<ValueTraits> + , floating_point<FloatingPoint> + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value)); + }; +}; + +enum HookType +{ + Base, + Member, + NonMember +}; + +template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map, HookType Type> +class test_main_template; + +template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, FloatingPoint, DefaultHolder, Map, Base> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //base + typedef typename testval_traits_t::base_value_traits base_hook_t; + test::test_generic_set + < rebinder<base_hook_t, FloatingPoint, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, FloatingPoint, DefaultHolder, Map, Member> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //member + typedef typename testval_traits_t::member_value_traits member_hook_t; + test::test_generic_set + < rebinder<member_hook_t, FloatingPoint, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, FloatingPoint, DefaultHolder, Map, NonMember> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //nonmember + test::test_generic_set + < rebinder<typename testval_traits_t::nonhook_value_traits, FloatingPoint, DefaultHolder, Map> + >::test_all(); + } +}; + +template < bool FloatingPoint, 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<allocator_type> bounded_scope; (void)bounded_scope; + test::test_generic_set + < rebinder< value_traits, FloatingPoint, true, Map> + >::test_all(); + } +}; + +int main() +{ + //Combinations: VoidPointer x FloatingPoint 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<void*, false, false, false, Base>::execute(); + //test_main_template<void*, false, false, true>::execute(); + test_main_template<void*, false, true, false, Member>::execute(); + //test_main_template<void*, false, true, true>::execute(); + test_main_template<void*, true, false, false, Base>::execute(); + //test_main_template<void*, true, false, true>::execute(); + test_main_template<void*, true, true, false, Member>::execute(); + test_main_template<void*, true, true, true, NonMember>::execute(); + + //smart_ptr + //test_main_template<smart_ptr<void>, false, false, false>::execute(); + test_main_template<smart_ptr<void>, false, false, true, Base>::execute(); + //test_main_template<smart_ptr<void>, false, true, false>::execute(); + test_main_template<smart_ptr<void>, false, true, true, Member>::execute(); + //test_main_template<smart_ptr<void>, true, false, false>::execute(); + test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute(); + //test_main_template<smart_ptr<void>, true, true, false>::execute(); + //test_main_template<smart_ptr<void>, true, true, true>::execute(); + + //bounded_ptr (bool FloatingPoint, 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/src/boost/libs/intrusive/test/slist_test.cpp b/src/boost/libs/intrusive/test/slist_test.cpp new file mode 100644 index 00000000..8a5362f8 --- /dev/null +++ b/src/boost/libs/intrusive/test/slist_test.cpp @@ -0,0 +1,660 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2013. +// +// 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 <boost/intrusive/slist.hpp> +#include <boost/intrusive/pointer_traits.hpp> +#include "itestvalue.hpp" +#include "bptr_value.hpp" +#include "smart_ptr.hpp" +#include "common_functors.hpp" +#include <vector> +#include <boost/detail/lightweight_test.hpp> +#include "test_macros.hpp" +#include "test_container.hpp" +#include <typeinfo> + +using namespace boost::intrusive; + +template<class VoidPointer> +struct hooks +{ + typedef slist_base_hook<void_pointer<VoidPointer> > base_hook_type; + typedef slist_base_hook< link_mode<auto_unlink> + , void_pointer<VoidPointer>, tag<void> > auto_base_hook_type; + typedef slist_member_hook<void_pointer<VoidPointer>, tag<void> > member_hook_type; + typedef slist_member_hook< link_mode<auto_unlink> + , void_pointer<VoidPointer> > auto_member_hook_type; + typedef nonhook_node_member< slist_node_traits< VoidPointer >, + circular_slist_algorithms + > nonhook_node_member_type; +}; + +template < typename ListType, typename ValueContainer > +struct test_slist +{ + typedef ListType list_type; + typedef typename list_type::value_traits value_traits; + typedef typename value_traits::value_type value_type; + typedef typename list_type::node_algorithms node_algorithms; + + static void test_all(ValueContainer&); + static void test_front(ValueContainer&); + static void test_back(ValueContainer&, detail::true_type); + static void test_back(ValueContainer&, detail::false_type) {} + static void test_sort(ValueContainer&); + static void test_merge(ValueContainer&); + static void test_remove_unique(ValueContainer&); + static void test_insert(ValueContainer&); + static void test_shift(ValueContainer&); + static void test_swap(ValueContainer&); + static void test_slow_insert(ValueContainer&); + static void test_clone(ValueContainer&); + static void test_container_from_end(ValueContainer&, detail::true_type); + static void test_container_from_end(ValueContainer&, detail::false_type) {} +}; + +template < typename ListType, typename ValueContainer > +void test_slist< ListType, ValueContainer > + ::test_all (ValueContainer& values) +{ + { + list_type list(values.begin(), values.end()); + test::test_container(list); + list.clear(); + list.insert(list.end(), values.begin(), values.end()); + test::test_sequence_container(list, values); + } + { + list_type list(values.begin(), values.end()); + test::test_iterator_forward(list); + } + test_front(values); + test_back(values, detail::bool_< list_type::cache_last >()); + test_sort(values); + test_merge (values); + test_remove_unique(values); + test_insert(values); + test_shift(values); + test_slow_insert (values); + test_swap(values); + test_clone(values); + test_container_from_end(values, detail::bool_< !list_type::linear && list_type::has_container_from_iterator >()); +} + +//test: push_front, pop_front, front, size, empty: +template < typename ListType, typename ValueContainer > +void test_slist< ListType, ValueContainer > + ::test_front(ValueContainer& values) +{ + list_type testlist; + BOOST_TEST (testlist.empty()); + + testlist.push_front (values[0]); + BOOST_TEST (testlist.size() == 1); + BOOST_TEST (&testlist.front() == &values[0]); + + testlist.push_front (values[1]); + BOOST_TEST (testlist.size() == 2); + BOOST_TEST (&testlist.front() == &values[1]); + + testlist.pop_front(); + BOOST_TEST (testlist.size() == 1); + BOOST_TEST (&testlist.front() == &values[0]); + + testlist.pop_front(); + BOOST_TEST (testlist.empty()); +} + +//test: push_front, pop_front, front, size, empty: +template < typename ListType, typename ValueContainer > +void test_slist< ListType, ValueContainer > + ::test_back(ValueContainer& values, detail::true_type) +{ + list_type testlist; + BOOST_TEST (testlist.empty()); + + testlist.push_back (values[0]); + BOOST_TEST (testlist.size() == 1); + BOOST_TEST (&testlist.front() == &values[0]); + BOOST_TEST (&testlist.back() == &values[0]); + testlist.push_back(values[1]); + BOOST_TEST(*testlist.previous(testlist.end()) == values[1]); + BOOST_TEST (&testlist.front() == &values[0]); + BOOST_TEST (&testlist.back() == &values[1]); +} + +//test: merge due to error in merge implementation: +template < typename ListType, typename ValueContainer > +void test_slist< ListType, ValueContainer > + ::test_merge (ValueContainer& values) +{ + list_type testlist1, testlist2; + testlist1.push_front (values[0]); + testlist2.push_front (values[4]); + testlist2.push_front (values[3]); + testlist2.push_front (values[2]); + testlist1.merge (testlist2); + + int init_values [] = { 1, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); +} + +//test: merge due to error in merge implementation: +template < typename ListType, typename ValueContainer > +void test_slist< ListType, ValueContainer > + ::test_remove_unique (ValueContainer& values) +{ + { + list_type list(values.begin(), values.end()); + list.remove_if(is_even()); + int init_values [] = { 1, 3, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() ); + } + { + list_type list(values.begin(), values.end()); + list.remove_if(is_odd()); + int init_values [] = { 2, 4 }; + TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() ); + } + { + list_type list(values.begin(), values.end()); + list.remove_and_dispose_if(is_even(), test::empty_disposer()); + int init_values [] = { 1, 3, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() ); + } + { + list_type list(values.begin(), values.end()); + list.remove_and_dispose_if(is_odd(), test::empty_disposer()); + int init_values [] = { 2, 4 }; + TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() ); + } + { + ValueContainer values2(values); + list_type list(values.begin(), values.end()); + list.insert_after(list.before_begin(), values2.begin(), values2.end()); + list.sort(); + int init_values [] = { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() ); + list.unique(); + int init_values2 [] = { 1, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values2, list.begin() ); + } +} + +//test: constructor, iterator, sort, reverse: +template < typename ListType, typename ValueContainer > +void test_slist< ListType, ValueContainer > + ::test_sort(ValueContainer& values) +{ + list_type testlist (values.begin(), values.end()); + + { int init_values [] = { 1, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); } + + testlist.sort (even_odd()); + { int init_values [] = { 2, 4, 1, 3, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); } + + testlist.reverse(); + { int init_values [] = { 5, 3, 1, 4, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); } +} + +//test: assign, insert_after, const_iterator, erase_after, s_iterator_to, previous: +template < typename ListType, typename ValueContainer > +void test_slist< ListType, ValueContainer > + ::test_insert(ValueContainer& values) +{ + list_type testlist; + testlist.assign (values.begin() + 2, values.begin() + 5); + + const list_type& const_testlist = testlist; + { int init_values [] = { 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); } + + typename list_type::iterator i = ++testlist.begin(); + BOOST_TEST (i->value_ == 4); + + testlist.insert_after (i, values[0]); + { int init_values [] = { 3, 4, 1, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); } + + i = testlist.iterator_to (values[4]); + BOOST_TEST (&*i == &values[4]); + i = list_type::s_iterator_to (values[4]); + BOOST_TEST (&*i == &values[4]); + + typename list_type::const_iterator ic; + ic = testlist.iterator_to (static_cast< typename list_type::const_reference >(values[4])); + BOOST_TEST (&*ic == &values[4]); + ic = list_type::s_iterator_to (static_cast< typename list_type::const_reference >(values[4])); + BOOST_TEST (&*ic == &values[4]); + + i = testlist.previous (i); + BOOST_TEST (&*i == &values[0]); + + testlist.erase_after (i); + BOOST_TEST (&*i == &values[0]); + { int init_values [] = { 3, 4, 1 }; + TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); } +} + +//test: insert, const_iterator, erase, siterator_to: +template < typename ListType, typename ValueContainer > +void test_slist< ListType, ValueContainer > + ::test_slow_insert (ValueContainer& values) +{ + list_type testlist; + testlist.push_front (values[4]); + testlist.insert (testlist.begin(), values.begin() + 2, values.begin() + 4); + + const list_type& const_testlist = testlist; + { int init_values [] = { 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); } + + typename list_type::iterator i = ++testlist.begin(); + BOOST_TEST (i->value_ == 4); + + testlist.insert (i, values[0]); + { int init_values [] = { 3, 1, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); } + + i = testlist.iterator_to (values[4]); + BOOST_TEST (&*i == &values[4]); + + i = list_type::s_iterator_to (values[4]); + BOOST_TEST (&*i == &values[4]); + + i = testlist.erase (i); + BOOST_TEST (i == testlist.end()); + + { int init_values [] = { 3, 1, 4 }; + TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); } + + testlist.erase (++testlist.begin(), testlist.end()); + BOOST_TEST (testlist.size() == 1); + BOOST_TEST (testlist.begin()->value_ == 3); +} + +template < typename ListType, typename ValueContainer > +void test_slist< ListType, ValueContainer > + ::test_shift(ValueContainer& values) +{ + list_type testlist; + const int num_values = (int)values.size(); + std::vector<int> expected_values(num_values); + + //Shift forward all possible positions 3 times + for(int s = 1; s <= num_values; ++s){ + expected_values.resize(s); + for(int i = 0; i < s*3; ++i){ + testlist.insert_after(testlist.before_begin(), values.begin(), values.begin() + s); + testlist.shift_forward(i); + for(int j = 0; j < s; ++j){ + expected_values[(j + s - i%s) % s] = (j + 1); + } + + TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin()) + testlist.clear(); + } + + //Shift backwards all possible positions + for(int i = 0; i < s*3; ++i){ + testlist.insert_after(testlist.before_begin(), values.begin(), values.begin() + s); + testlist.shift_backwards(i); + for(int j = 0; j < s; ++j){ + expected_values[(j + i) % s] = (j + 1); + } + + TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin()) + testlist.clear(); + } + } +} + +//test: insert_after (seq-version), swap, splice_after: +template < typename ListType, typename ValueContainer > +void test_slist< ListType, ValueContainer > + ::test_swap(ValueContainer& values) +{ + { + list_type testlist1 (values.begin(), values.begin() + 2); + list_type testlist2; + testlist2.insert_after (testlist2.before_begin(), values.begin() + 2, values.begin() + 5); + testlist1.swap(testlist2); + { int init_values [] = { 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + { int init_values [] = { 1, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } + testlist2.splice_after (testlist2.begin(), testlist1); + { int init_values [] = { 1, 3, 4, 5, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } + BOOST_TEST (testlist1.empty()); + + testlist1.splice_after (testlist1.before_begin(), testlist2, ++testlist2.begin()); + { int init_values [] = { 4 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + { int init_values [] = { 1, 3, 5, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } + + testlist1.splice_after (testlist1.begin(), testlist2, + testlist2.before_begin(), ++++testlist2.begin()); + { int init_values [] = { 4, 1, 3, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + { int init_values [] = { 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } + } + { //Now test swap when testlist2 is empty + list_type testlist1 (values.begin(), values.begin() + 2); + list_type testlist2; + testlist1.swap(testlist2); + BOOST_TEST (testlist1.empty()); + { int init_values [] = { 1, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } + } + { //Now test swap when testlist1 is empty + list_type testlist2 (values.begin(), values.begin() + 2); + list_type testlist1; + testlist1.swap(testlist2); + BOOST_TEST (testlist2.empty()); + { int init_values [] = { 1, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + } + { //Now test when both are empty + list_type testlist1, testlist2; + testlist2.swap(testlist1); + BOOST_TEST (testlist1.empty() && testlist2.empty()); + } + + if(!list_type::linear) + { + list_type testlist1 (values.begin(), values.begin() + 2); + list_type testlist2 (values.begin() + 3, values.begin() + 5); + + swap_nodes< node_algorithms >(values[0], values[2]); + { int init_values [] = { 3, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + + swap_nodes< node_algorithms >(values[2], values[4]); + { int init_values [] = { 5, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + { int init_values [] = { 4, 3 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } + } + if(!list_type::linear) + { + list_type testlist1 (values.begin(), values.begin()+1); + if(testlist1.size() != 1){ + abort(); + } + { int init_values [] = { 1 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + + swap_nodes< node_algorithms >(values[1], values[2]); + + BOOST_TEST(testlist1.size() == 1); + BOOST_TEST(!(&values[1])->is_linked()); + BOOST_TEST(!(&values[2])->is_linked()); + { int init_values [] = { 1 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + + swap_nodes< node_algorithms >(values[0], values[2]); + BOOST_TEST(testlist1.size() == 1); + BOOST_TEST((&values[2])->is_linked()); + BOOST_TEST(!(&values[0])->is_linked()); + { int init_values [] = { 3 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + + swap_nodes< node_algorithms >(values[0], values[2]); + BOOST_TEST(testlist1.size() == 1); + BOOST_TEST(!(&values[2])->is_linked()); + BOOST_TEST((&values[0])->is_linked()); + { int init_values [] = { 1 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + } +} + +template < typename ListType, typename ValueContainer > +void test_slist< ListType, ValueContainer > + ::test_clone(ValueContainer& values) +{ + list_type testlist1 (values.begin(), values.begin() + values.size()); + list_type testlist2; + + testlist2.clone_from(testlist1, test::new_cloner<value_type>(), test::delete_disposer<value_type>()); + BOOST_TEST (testlist2 == testlist1); + testlist2.clear_and_dispose(test::delete_disposer<value_type>()); + BOOST_TEST (testlist2.empty()); +} + +template < typename ListType, typename ValueContainer > +void test_slist< ListType, ValueContainer > + ::test_container_from_end(ValueContainer& values, detail::true_type) +{ + list_type testlist1 (values.begin(), values.begin() + values.size()); + BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.end())); + BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.cend())); +} + +template < typename ValueTraits, bool ConstantTimeSize, bool Linear, bool CacheLast, bool Default_Holder, typename ValueContainer > +struct make_and_test_slist + : test_slist< slist< typename ValueTraits::value_type, + value_traits< ValueTraits >, + size_type< std::size_t >, + constant_time_size< ConstantTimeSize >, + linear<Linear>, + cache_last<CacheLast> + >, + ValueContainer + > +{}; + +template < typename ValueTraits, bool ConstantTimeSize, bool Linear, bool CacheLast, typename ValueContainer > +struct make_and_test_slist< ValueTraits, ConstantTimeSize, Linear, CacheLast, false, ValueContainer > + : test_slist< slist< typename ValueTraits::value_type, + value_traits< ValueTraits >, + size_type< std::size_t >, + constant_time_size< ConstantTimeSize >, + linear<Linear>, + cache_last<CacheLast>, + header_holder_type< heap_node_holder< typename ValueTraits::pointer > > + >, + ValueContainer + > +{}; + +template<class VoidPointer, bool constant_time_size, bool Default_Holder> +class test_main_template +{ + public: + int operator()() + { + typedef testvalue< hooks<VoidPointer> > value_type; + std::vector< value_type > data (5); + for (int i = 0; i < 5; ++i) + data[i].value_ = i + 1; + + make_and_test_slist < typename detail::get_base_value_traits + < value_type + , typename hooks<VoidPointer>::base_hook_type + >::type + , constant_time_size + , false + , false + , Default_Holder + , std::vector< value_type > + >::test_all(data); + make_and_test_slist < nonhook_node_member_value_traits< value_type, + typename hooks<VoidPointer>::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + > + , constant_time_size + , false + , false + , Default_Holder + , std::vector< value_type > + >::test_all(data); + + //Now linear slists + make_and_test_slist < typename detail::get_member_value_traits + < member_hook< value_type + , typename hooks<VoidPointer>::member_hook_type + , &value_type::node_ + > + >::type + , constant_time_size + , true + , false + , Default_Holder + , std::vector< value_type > + >::test_all(data); + + //Now the same but caching the last node + make_and_test_slist < typename detail::get_base_value_traits + < value_type + , typename hooks<VoidPointer>::base_hook_type + >::type + , constant_time_size + , false + , true + , Default_Holder + , std::vector< value_type > + >::test_all(data); + + //Now linear slists + make_and_test_slist < typename detail::get_base_value_traits + < value_type + , typename hooks<VoidPointer>::base_hook_type + >::type + , constant_time_size + , true + , true + , Default_Holder + , std::vector< value_type > + >::test_all(data); + return 0; + } +}; + +template<class VoidPointer, bool Default_Holder> +class test_main_template<VoidPointer, false, Default_Holder> +{ + public: + int operator()() + { + typedef testvalue< hooks<VoidPointer> > value_type; + std::vector< value_type > data (5); + for (int i = 0; i < 5; ++i) + data[i].value_ = i + 1; + + make_and_test_slist < typename detail::get_base_value_traits + < value_type + , typename hooks<VoidPointer>::auto_base_hook_type + >::type + , false + , false + , false + , Default_Holder + , std::vector< value_type > + >::test_all(data); + + make_and_test_slist < nonhook_node_member_value_traits< value_type, + typename hooks<VoidPointer>::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + > + , false + , false + , true + , Default_Holder + , std::vector< value_type > + >::test_all(data); + + make_and_test_slist < typename detail::get_member_value_traits + < member_hook< value_type + , typename hooks<VoidPointer>::member_hook_type + , &value_type::node_ + > + >::type + , false + , true + , false + , Default_Holder + , std::vector< value_type > + >::test_all(data); + + make_and_test_slist < typename detail::get_base_value_traits + < value_type + , typename hooks<VoidPointer>::base_hook_type + >::type + , false + , true + , true + , Default_Holder + , std::vector< value_type > + >::test_all(data); + + return 0; + } +}; + +template < bool ConstantTimeSize > +struct test_main_template_bptr +{ + int operator()() + { + typedef BPtr_Value value_type; + typedef BPtr_Value_Traits< List_BPtr_Node_Traits > list_value_traits; + typedef typename list_value_traits::node_ptr node_ptr; + typedef bounded_allocator< value_type > allocator_type; + + bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope; + allocator_type allocator; + + { + bounded_reference_cont< value_type > ref_cont; + for (int i = 0; i < 5; ++i) + { + node_ptr tmp = allocator.allocate(1); + new (tmp.raw()) value_type(i + 1); + ref_cont.push_back(*tmp); + } + + test_slist < slist < value_type, + value_traits< list_value_traits >, + size_type< std::size_t >, + constant_time_size< ConstantTimeSize >, + header_holder_type< bounded_pointer_holder< value_type > > + >, + bounded_reference_cont< value_type > + >::test_all(ref_cont); + } + return 0; + } +}; + +int main(int, char* []) +{ + // test (plain/smart pointers) x (nonconst/const size) x (void node allocator) + test_main_template<void*, false, true>()(); + test_main_template<boost::intrusive::smart_ptr<void>, false, true>()(); + test_main_template<void*, true, true>()(); + test_main_template<boost::intrusive::smart_ptr<void>, true, true>()(); + // test (bounded pointers) x ((nonconst/const size) x (special node allocator) + test_main_template_bptr< true >()(); + test_main_template_bptr< false >()(); + + + return boost::report_errors(); +} diff --git a/src/boost/libs/intrusive/test/smart_ptr.hpp b/src/boost/libs/intrusive/test/smart_ptr.hpp new file mode 100644 index 00000000..10e54853 --- /dev/null +++ b/src/boost/libs/intrusive/test/smart_ptr.hpp @@ -0,0 +1,311 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. 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_SMART_PTR_HPP +#define BOOST_INTRUSIVE_SMART_PTR_HPP + +#include <boost/intrusive/pointer_plus_bits.hpp> +#include <boost/intrusive/pointer_traits.hpp> +#include <boost/intrusive/detail/iterator.hpp> +#include <boost/move/adl_move_swap.hpp> + +#if (defined _MSC_VER) +# pragma once +#endif + +namespace boost{ +namespace intrusive{ + +namespace detail { + +struct static_cast_tag {}; +struct const_cast_tag {}; +struct dynamic_cast_tag {}; +struct reinterpret_cast_tag {}; + +} //namespace detail { + +//Empty class +struct empty_type{}; + +template<class T> +struct random_it +: public iterator<std::random_access_iterator_tag, T, std::ptrdiff_t, T*, T&> +{ + typedef const T* const_pointer; + typedef const T& const_reference; +}; + +template<> struct random_it<void> +{ + typedef const void * const_pointer; + typedef empty_type& reference; + typedef const empty_type& const_reference; + typedef empty_type difference_type; + typedef empty_type iterator_category; +}; + +template<> struct random_it<const void> +{ + typedef const void * const_pointer; + typedef const empty_type & reference; + typedef const empty_type & const_reference; + typedef empty_type difference_type; + typedef empty_type iterator_category; +}; + +template<> struct random_it<volatile void> +{ + typedef const volatile void * const_pointer; + typedef empty_type& reference; + typedef const empty_type& const_reference; + typedef empty_type difference_type; + typedef empty_type iterator_category; +}; + +template<> struct random_it<const volatile void> +{ + typedef const volatile void * const_pointer; + typedef const empty_type & reference; + typedef const empty_type & const_reference; + typedef empty_type difference_type; + typedef empty_type iterator_category; +}; + +} //namespace intrusive { +} //namespace boost { + + +namespace boost { +namespace intrusive { + +template <class PointedType> +class smart_ptr +{ + typedef random_it<PointedType> random_it_t; + typedef smart_ptr<PointedType> self_t; + typedef typename random_it_t::const_pointer const_pointer_t; + typedef typename random_it_t::const_reference const_reference_t; + + void unspecified_bool_type_func() const {} + typedef void (self_t::*unspecified_bool_type)() const; + + public: + typedef PointedType * pointer; + typedef typename random_it_t::reference reference; + typedef PointedType value_type; + typedef typename random_it_t::difference_type difference_type; + typedef typename random_it_t::iterator_category iterator_category; + + PointedType *m_ptr; + + public: //Public Functions + + smart_ptr() + : m_ptr(0) + {} + + //!Constructor from other smart_ptr + smart_ptr(const smart_ptr& ptr) + : m_ptr(ptr.m_ptr) + {} + + static smart_ptr pointer_to(reference r) + { smart_ptr p; p.m_ptr = &r; return p; } + + //!Constructor from other smart_ptr. If pointers of pointee types are + //!convertible, offset_ptrs will be convertibles. Never throws. + template<class T2> + smart_ptr(const smart_ptr<T2> &ptr) + : m_ptr(ptr.m_ptr) + {} + + pointer get() const + { return m_ptr; } + + void set(pointer p) + { m_ptr = p; } + + //!Pointer-like -> operator. It can return 0 pointer. Never throws. + pointer operator->() const + { return m_ptr; } + + //!Dereferencing operator, if it is a null smart_ptr behavior + //! is undefined. Never throws. + reference operator* () const + { return *m_ptr; } + + //!Indexing operator. Never throws. + reference operator[](std::ptrdiff_t idx) const + { return m_ptr[idx]; } + + //!Assignment from other smart_ptr. Never throws. + smart_ptr& operator= (const smart_ptr & pt) + { m_ptr = pt.m_ptr; return *this; } + + //!Assignment from related smart_ptr. If pointers of pointee types + //! are assignable, offset_ptrs will be assignable. Never throws. + template <class T2> + smart_ptr& operator= (const smart_ptr<T2> & pt) + { m_ptr = pt.m_ptr; return *this; } + + //!smart_ptr + std::ptrdiff_t. Never throws. + smart_ptr operator+ (std::ptrdiff_t offset) const + { smart_ptr s; s.m_ptr = m_ptr + offset; return s; } + + //!smart_ptr - std::ptrdiff_t. Never throws. + smart_ptr operator- (std::ptrdiff_t offset) const + { smart_ptr s; s.m_ptr = m_ptr - offset; return s; } + + //!smart_ptr += std::ptrdiff_t. Never throws. + smart_ptr &operator+= (std::ptrdiff_t offset) + { m_ptr += offset; return *this; } + + //!smart_ptr -= std::ptrdiff_t. Never throws. + smart_ptr &operator-= (std::ptrdiff_t offset) + { m_ptr -= offset; return *this; } + + //!++smart_ptr. Never throws. + smart_ptr& operator++ (void) + { ++m_ptr; return *this; } + + //!smart_ptr++. Never throws. + smart_ptr operator++ (int) + { smart_ptr temp(*this); ++*this; return temp; } + + //!--smart_ptr. Never throws. + smart_ptr& operator-- (void) + { --m_ptr; return *this; } + + //!smart_ptr--. Never throws. + smart_ptr operator-- (int) + { smart_ptr temp(*this); --*this; return temp; } + + //!safe bool conversion operator. Never throws. + operator unspecified_bool_type() const + { return m_ptr? &self_t::unspecified_bool_type_func : 0; } + + //!Not operator. Not needed in theory, but improves portability. + //!Never throws. + bool operator! () const + { return m_ptr == 0; } + + //!swap + friend void swap(smart_ptr& x, smart_ptr& y) + { boost::adl_move_swap(x.m_ptr, y.m_ptr); } +}; + +//!smart_ptr<T1> == smart_ptr<T2>. Never throws. +template<class T1, class T2> +inline bool operator== (const smart_ptr<T1> &pt1, + const smart_ptr<T2> &pt2) +{ return pt1.operator->() == pt2.operator->(); } + +//!smart_ptr<T1> != smart_ptr<T2>. Never throws. +template<class T1, class T2> +inline bool operator!= (const smart_ptr<T1> &pt1, + const smart_ptr<T2> &pt2) +{ return pt1.operator->() != pt2.operator->(); } + +//!smart_ptr<T1> < smart_ptr<T2>. Never throws. +template<class T1, class T2> +inline bool operator< (const smart_ptr<T1> &pt1, + const smart_ptr<T2> &pt2) +{ return pt1.operator->() < pt2.operator->(); } + +//!smart_ptr<T1> <= smart_ptr<T2>. Never throws. +template<class T1, class T2> +inline bool operator<= (const smart_ptr<T1> &pt1, + const smart_ptr<T2> &pt2) +{ return pt1.operator->() <= pt2.operator->(); } + +//!smart_ptr<T1> > smart_ptr<T2>. Never throws. +template<class T1, class T2> +inline bool operator> (const smart_ptr<T1> &pt1, + const smart_ptr<T2> &pt2) +{ return pt1.operator->() > pt2.operator->(); } + +//!smart_ptr<T1> >= smart_ptr<T2>. Never throws. +template<class T1, class T2> +inline bool operator>= (const smart_ptr<T1> &pt1, + const smart_ptr<T2> &pt2) +{ return pt1.operator->() >= pt2.operator->(); } + +//!operator<< +template<class E, class T, class Y> +inline std::basic_ostream<E, T> & operator<< + (std::basic_ostream<E, T> & os, smart_ptr<Y> const & p) +{ return os << p.operator->(); } + +//!operator>> +template<class E, class T, class Y> +inline std::basic_istream<E, T> & operator>> + (std::basic_istream<E, T> & os, smart_ptr<Y> & p) +{ Y * tmp; return os >> tmp; p = tmp; } + +//!std::ptrdiff_t + smart_ptr +template<class T> +inline smart_ptr<T> operator+(std::ptrdiff_t diff, const smart_ptr<T>& right) +{ return right + diff; } + +//!smart_ptr - smart_ptr +template<class T, class T2> +inline std::ptrdiff_t operator- (const smart_ptr<T> &pt, const smart_ptr<T2> &pt2) +{ return pt.operator->()- pt2.operator->(); } + +} //namespace intrusive { +} //namespace boost { + +namespace boost{ + +//This is to support embedding a bit in the pointer +//for intrusive containers, saving space +namespace intrusive { + +template<std::size_t Alignment> +struct max_pointer_plus_bits<smart_ptr<void>, Alignment> +{ + static const std::size_t value = max_pointer_plus_bits<void*, Alignment>::value; +}; + +template<class T, std::size_t NumBits> +struct pointer_plus_bits<smart_ptr<T>, NumBits> +{ + typedef smart_ptr<T> pointer; + + static pointer get_pointer(const pointer &n) + { + pointer p; + p.set(pointer_plus_bits<T*, NumBits>::get_pointer(n.get())); + return p; + } + + static void set_pointer(pointer &n, pointer p) + { + T *raw_n = n.get(); + pointer_plus_bits<T*, NumBits>::set_pointer(raw_n, p.operator->()); + n.set(raw_n); + } + + static std::size_t get_bits(const pointer &n) + { return pointer_plus_bits<T*, NumBits>::get_bits(n.get()); } + + static void set_bits(pointer &n, std::size_t c) + { + T *raw_n = n.operator->(); + pointer_plus_bits<T*, NumBits>::set_bits(raw_n, c); + n.set(raw_n); + } +}; + +} //namespace intrusive +} //namespace boost{ + +#endif //#ifndef BOOST_INTRUSIVE_SMART_PTR_HPP diff --git a/src/boost/libs/intrusive/test/splay_multiset_test.cpp b/src/boost/libs/intrusive/test/splay_multiset_test.cpp new file mode 100644 index 00000000..70fb8912 --- /dev/null +++ b/src/boost/libs/intrusive/test/splay_multiset_test.cpp @@ -0,0 +1,155 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2013 +// +// 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 <boost/intrusive/splay_set.hpp> +#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<ValueTraits, DefaultHolder, Map> common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef splay_multiset + < typename common_t::value_type + , value_traits<ValueTraits> + , constant_time_size<ConstantTimeSize> + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value)); + }; +}; + +enum HookType +{ + Base, + Member, + NonMember +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type> +class test_main_template; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > 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 + < rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //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 + < rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //nonmember + test::test_generic_multiset + < rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map> + >::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<allocator_type> bounded_scope; (void)bounded_scope; + test::test_generic_multiset + < 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<void*, false, false, false, Base>::execute(); + //test_main_template<void*, false, false, true>::execute(); + test_main_template<void*, false, true, false, Member>::execute(); + //test_main_template<void*, false, true, true>::execute(); + test_main_template<void*, true, false, false, Base>::execute(); + //test_main_template<void*, true, false, true>::execute(); + test_main_template<void*, true, true, false, Member>::execute(); + test_main_template<void*, true, true, true, NonMember>::execute(); + + //smart_ptr + //test_main_template<smart_ptr<void>, false, false, false>::execute(); + test_main_template<smart_ptr<void>, false, false, true, Base>::execute(); + //test_main_template<smart_ptr<void>, false, true, false>::execute(); + test_main_template<smart_ptr<void>, false, true, true, Member>::execute(); + //test_main_template<smart_ptr<void>, true, false, false>::execute(); + test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute(); + //test_main_template<smart_ptr<void>, true, true, false>::execute(); + //test_main_template<smart_ptr<void>, 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/src/boost/libs/intrusive/test/splay_set_test.cpp b/src/boost/libs/intrusive/test/splay_set_test.cpp new file mode 100644 index 00000000..7aa73b28 --- /dev/null +++ b/src/boost/libs/intrusive/test/splay_set_test.cpp @@ -0,0 +1,155 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-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 <boost/intrusive/splay_set.hpp> +#include "itestvalue.hpp" +#include "bptr_value.hpp" +#include "smart_ptr.hpp" +#include "bs_test_common.hpp" +#include "generic_set_test.hpp" + +using namespace boost::intrusive; + +template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map > +struct rebinder +{ + typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef splay_set + < typename common_t::value_type + , value_traits<ValueTraits> + , constant_time_size<ConstantTimeSize> + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value)); + }; +}; + +enum HookType +{ + Base, + Member, + NonMember +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type> +class test_main_template; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > 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 + < rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //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 + < rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //nonmember + test::test_generic_set + < rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map> + >::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<allocator_type> bounded_scope; (void)bounded_scope; + test::test_generic_set + < 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<void*, false, false, false, Base>::execute(); + //test_main_template<void*, false, false, true>::execute(); + test_main_template<void*, false, true, false, Member>::execute(); + //test_main_template<void*, false, true, true>::execute(); + test_main_template<void*, true, false, false, Base>::execute(); + //test_main_template<void*, true, false, true>::execute(); + test_main_template<void*, true, true, false, Member>::execute(); + test_main_template<void*, true, true, true, NonMember>::execute(); + + //smart_ptr + //test_main_template<smart_ptr<void>, false, false, false>::execute(); + test_main_template<smart_ptr<void>, false, false, true, Base>::execute(); + //test_main_template<smart_ptr<void>, false, true, false>::execute(); + test_main_template<smart_ptr<void>, false, true, true, Member>::execute(); + //test_main_template<smart_ptr<void>, true, false, false>::execute(); + test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute(); + //test_main_template<smart_ptr<void>, true, true, false>::execute(); + //test_main_template<smart_ptr<void>, 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/src/boost/libs/intrusive/test/stateful_value_traits_test.cpp b/src/boost/libs/intrusive/test/stateful_value_traits_test.cpp new file mode 100644 index 00000000..c24c8fb6 --- /dev/null +++ b/src/boost/libs/intrusive/test/stateful_value_traits_test.cpp @@ -0,0 +1,157 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2013 +// +// 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 <boost/intrusive/list.hpp> +#include <boost/intrusive/slist.hpp> +#include <boost/intrusive/set.hpp> +#include <boost/intrusive/unordered_set.hpp> +#include <boost/functional/hash.hpp> +#include <boost/intrusive/pointer_traits.hpp> +#include <vector> + +using namespace boost::intrusive; + +class MyClass +{ + public: + int int_; + + MyClass(int i = 0) + : int_(i) + {} + + friend bool operator<(const MyClass &l, const MyClass &r) + { return l.int_ < r.int_; } + + friend bool operator==(const MyClass &l, const MyClass &r) + { return l.int_ == r.int_; } + + friend std::size_t hash_value(const MyClass &v) + { return boost::hash_value(v.int_); } +}; + +template<class T, class NodeTraits> +struct stateful_value_traits +{ + typedef NodeTraits node_traits; + typedef typename node_traits::node node; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; + typedef T value_type; + typedef typename pointer_traits<node_ptr>:: + template rebind_pointer<T>::type pointer; + typedef typename pointer_traits<node_ptr>:: + template rebind_pointer<const T>::type const_pointer; + + static const link_mode_type link_mode = normal_link; + + stateful_value_traits(pointer vals, node_ptr node_array) + : values_(vals), node_array_(node_array) + {} + + node_ptr to_node_ptr (value_type &value) const + { return node_array_ + (&value - values_); } + + const_node_ptr to_node_ptr (const value_type &value) const + { return node_array_ + (&value - values_); } + + pointer to_value_ptr(const node_ptr &n) const + { return values_ + (n - node_array_); } + + const_pointer to_value_ptr(const const_node_ptr &n) const + { return values_ + (n - node_array_); } + + pointer values_; + node_ptr node_array_; +}; + +//Define a list that will store MyClass using the external hook +typedef stateful_value_traits< MyClass, list_node_traits<void*> > list_traits; +typedef list<MyClass, value_traits<list_traits> > List; + +//Define a slist that will store MyClass using the external hook +typedef stateful_value_traits< MyClass, slist_node_traits<void*> > slist_traits; +typedef slist<MyClass, value_traits<slist_traits> > Slist; + +//Define a set that will store MyClass using the external hook +typedef stateful_value_traits< MyClass, rbtree_node_traits<void*> > rbtree_traits; +typedef set<MyClass, value_traits<rbtree_traits> > Set; + +//uset uses the same traits as slist +typedef unordered_set<MyClass, value_traits<slist_traits> > Uset; + + +typedef list_traits::node list_node_t; +typedef slist_traits::node slist_node_t; +typedef rbtree_traits::node rbtree_node_t; + +const int NumElements = 100; + +MyClass values [NumElements]; +list_node_t list_hook_array [NumElements]; +slist_node_t slist_hook_array [NumElements]; +rbtree_node_t rbtree_hook_array [NumElements]; +slist_node_t uset_hook_array [NumElements]; + +int main() +{ + //Create several MyClass objects, each one with a different value + for(int i = 0; i < NumElements; ++i) + values[i].int_ = i; + + Uset::bucket_type buckets[NumElements]; + + List my_list (list_traits (values, list_hook_array)); + Slist my_slist(slist_traits(values, slist_hook_array)); + Set my_set (std::less<MyClass>(), rbtree_traits(values, rbtree_hook_array)); + Uset my_uset ( Uset::bucket_traits(buckets, NumElements) + , boost::hash<MyClass>() + , std::equal_to<MyClass>() + , slist_traits(values, uset_hook_array) + ); + + //Now insert them in containers + for(MyClass * it(&values[0]), *itend(&values[NumElements]) + ; it != itend + ; ++it){ + my_list.push_front(*it); + if(&*my_list.iterator_to(*it) != &my_list.front()) + return 1; + my_slist.push_front(*it); + if(&*my_slist.iterator_to(*it) != &my_slist.front()) + return 1; + Set::iterator sit = my_set.insert(*it).first; + if(&*my_set.iterator_to(*it) != &*sit) + return 1; + Uset::iterator uit = my_uset.insert(*it).first; + my_uset.insert(*it); + if(&*my_uset.iterator_to(*it) != &*uit) + return 1; + } + + //Now test lists + { + List::const_iterator list_it (my_list.cbegin()); + Slist::const_iterator slist_it(my_slist.cbegin()); + Set::const_reverse_iterator set_rit(my_set.crbegin()); + MyClass *it_val(&values[NumElements]), *it_rbeg_val(&values[0]); + + //Test the objects inserted in the base hook list + for(; it_val != it_rbeg_val; --it_val, ++list_it, ++slist_it, ++set_rit){ + if(&*list_it != &it_val[-1]) return 1; + if(&*slist_it != &it_val[-1]) return 1; + if(&*set_rit != &it_val[-1]) return 1; + if(my_uset.find(it_val[-1]) == my_uset.cend()) return 1; + } + } + + return 0; +} diff --git a/src/boost/libs/intrusive/test/test_common.hpp b/src/boost/libs/intrusive/test/test_common.hpp new file mode 100644 index 00000000..8c7ae489 --- /dev/null +++ b/src/boost/libs/intrusive/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 <boost/intrusive/bs_set_hook.hpp> +#include <boost/intrusive/detail/mpl.hpp> +#include "bptr_value.hpp" + +namespace boost { +namespace intrusive { + +template <class KeyOfValueOption, class Map> +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<int_holder_key_of_value<typename Map::value_type> > + >::value )); + BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same< key_of_value_t + , int_holder_key_of_value<typename Map::value_type> + >::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 <class Map> +struct key_type_tester<void, Map> +{ + 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/src/boost/libs/intrusive/test/test_container.hpp b/src/boost/libs/intrusive/test/test_container.hpp new file mode 100644 index 00000000..6e98071f --- /dev/null +++ b/src/boost/libs/intrusive/test/test_container.hpp @@ -0,0 +1,572 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2013 +// +// 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_CONTAINER_HPP +#define BOOST_INTRUSIVE_TEST_CONTAINER_HPP + +#include <boost/detail/lightweight_test.hpp> +#include <boost/intrusive/detail/mpl.hpp> +#include <boost/intrusive/detail/simple_disposers.hpp> +#include <boost/intrusive/detail/iterator.hpp> +#include <boost/move/utility_core.hpp> +#include <boost/move/adl_move_swap.hpp> +#include <boost/intrusive/detail/mpl.hpp> +#include <boost/static_assert.hpp> +#include "iterator_test.hpp" +#include <cstdlib> + +namespace boost { +namespace intrusive { +namespace test { + +BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(is_unordered, hasher) + +template<class Container> +struct test_container_typedefs +{ + typedef typename Container::value_type value_type; + typedef typename Container::iterator iterator; + typedef typename Container::const_iterator const_iterator; + typedef typename Container::reference reference; + typedef typename Container::const_reference const_reference; + typedef typename Container::pointer pointer; + typedef typename Container::const_pointer const_pointer; + typedef typename Container::difference_type difference_type; + typedef typename Container::size_type size_type; + typedef typename Container::value_traits value_traits; +}; + +template< class Container > +void test_container( Container & c ) +{ + typedef typename Container::const_iterator const_iterator; + typedef typename Container::iterator iterator; + typedef typename Container::size_type size_type; + + {test_container_typedefs<Container> dummy; (void)dummy;} + const size_type num_elem = c.size(); + BOOST_TEST( c.empty() == (num_elem == 0) ); + { + iterator it(c.begin()), itend(c.end()); + size_type i; + for(i = 0; i < num_elem; ++i){ + ++it; + } + BOOST_TEST( it == itend ); + BOOST_TEST( c.size() == i ); + } + + //Check iterator conversion + BOOST_TEST(const_iterator(c.begin()) == c.cbegin() ); + { + const_iterator it(c.cbegin()), itend(c.cend()); + size_type i; + for(i = 0; i < num_elem; ++i){ + ++it; + } + BOOST_TEST( it == itend ); + BOOST_TEST( c.size() == i ); + } + static_cast<const Container&>(c).check(); + //Very basic test for comparisons + { + BOOST_TEST(c == c); + BOOST_TEST(!(c != c)); + BOOST_TEST(!(c < c)); + BOOST_TEST(c <= c); + BOOST_TEST(!(c > c)); + BOOST_TEST(c >= c); + } +} + + +template< class Container, class Data > +void test_sequence_container(Container & c, Data & d) +{ + assert( d.size() > 2 ); + { + c.clear(); + + BOOST_TEST( c.size() == 0 ); + BOOST_TEST( c.empty() ); + + + { + typename Data::iterator i = d.begin(); + c.insert( c.begin(), *i ); + BOOST_TEST( &*c.iterator_to(*c.begin()) == &*i ); + BOOST_TEST( &*c.iterator_to(*c.cbegin()) == &*i ); + BOOST_TEST( &*Container::s_iterator_to(*c.begin()) == &*i ); + BOOST_TEST( &*Container::s_iterator_to(*c.cbegin()) == &*i ); + c.insert( c.end(), *(++i) ); + } + BOOST_TEST( c.size() == 2 ); + BOOST_TEST( !c.empty() ); + + typename Container::iterator i; + i = c.erase( c.begin() ); + + BOOST_TEST( c.size() == 1 ); + BOOST_TEST( !c.empty() ); + + i = c.erase( c.begin() ); + + BOOST_TEST( c.size() == 0 ); + BOOST_TEST( c.empty() ); + + c.insert( c.begin(), *d.begin() ); + + BOOST_TEST( c.size() == 1 ); + BOOST_TEST( !c.empty() ); + + { + typename Data::iterator di = d.begin(); + ++++di; + c.insert( c.begin(), *(di) ); + } + + i = c.erase( c.begin(), c.end() ); + BOOST_TEST( i == c.end() ); + + BOOST_TEST( c.empty() ); + + c.insert( c.begin(), *d.begin() ); + + BOOST_TEST( c.size() == 1 ); + + BOOST_TEST( c.begin() != c.end() ); + + i = c.erase_and_dispose( c.begin(), detail::null_disposer() ); + BOOST_TEST( i == c.begin() ); + + c.assign(d.begin(), d.end()); + + BOOST_TEST( c.size() == d.size() ); + + c.clear(); + + BOOST_TEST( c.size() == 0 ); + BOOST_TEST( c.empty() ); + } + { + c.clear(); + c.insert( c.begin(), d.begin(), d.end() ); + Container move_c(::boost::move(c)); + BOOST_TEST( move_c.size() == d.size() ); + BOOST_TEST( c.empty()); + + c = ::boost::move(move_c); + BOOST_TEST( c.size() == d.size() ); + BOOST_TEST( move_c.empty()); + } +} + +template< class Container, class Data > +void test_common_unordered_and_associative_container(Container & c, Data & d, boost::intrusive::detail::true_ unordered) +{ + (void)unordered; + typedef typename Container::size_type size_type; + typedef typename Container::key_of_value key_of_value; + typedef typename Container::iterator iterator; + typedef typename Container::const_iterator const_iterator; + + assert( d.size() > 2 ); + + c.clear(); + c.insert(d.begin(), d.end()); + + { + Container const &cc = c; + for( typename Data::const_iterator di = d.begin(), de = d.end(); + di != de; ++di ) + { + BOOST_TEST( cc.find(key_of_value()(*di), c.hash_function(), c.key_eq()) != cc.end() ); + std::pair<const_iterator, const_iterator> rdi = cc.equal_range(key_of_value()(*di), c.hash_function(), c.key_eq()); + BOOST_TEST(rdi.first != rdi.second); + BOOST_TEST(size_type(boost::intrusive::iterator_distance(rdi.first, rdi.second)) == cc.count(key_of_value()(*di), c.hash_function(), c.key_eq())); + } + + for( iterator ci = c.begin(), ce = c.end(); ci != ce; ) + { + BOOST_TEST( c.find(key_of_value()(*ci)) != c.end() ); + std::pair<iterator, iterator> rci = c.equal_range(key_of_value()(*ci), c.hash_function(), c.key_eq()); + BOOST_TEST(rci.first != rci.second); + size_type const sc = c.count(key_of_value()(*ci), c.hash_function(), c.key_eq()); + BOOST_TEST(size_type(boost::intrusive::iterator_distance(rci.first, rci.second)) == sc); + BOOST_TEST(sc == c.erase(key_of_value()(*ci), c.hash_function(), c.key_eq())); + ci = rci.second; + } + BOOST_TEST(c.empty()); + } + + c.clear(); + c.insert(d.begin(), d.end()); + + typename Data::const_iterator db = d.begin(); + typename Data::const_iterator da = db++; + + size_type old_size = c.size(); + + c.erase(key_of_value()(*da), c.hash_function(), c.key_eq()); + BOOST_TEST( c.size() == old_size-1 ); + //This should not eras anyone + size_type second_erase = c.erase_and_dispose + ( key_of_value()(*da), c.hash_function(), c.key_eq(), detail::null_disposer() ); + BOOST_TEST( second_erase == 0 ); + + BOOST_TEST( c.count(key_of_value()(*da), c.hash_function(), c.key_eq()) == 0 ); + BOOST_TEST( c.count(key_of_value()(*db), c.hash_function(), c.key_eq()) != 0 ); + + BOOST_TEST( c.find(key_of_value()(*da), c.hash_function(), c.key_eq()) == c.end() ); + BOOST_TEST( c.find(key_of_value()(*db), c.hash_function(), c.key_eq()) != c.end() ); + + BOOST_TEST( c.equal_range(key_of_value()(*db), c.hash_function(), c.key_eq()).first != c.end() ); + + c.clear(); + + BOOST_TEST( c.equal_range(key_of_value()(*da), c.hash_function(), c.key_eq()).first == c.end() ); + + // + //suggested_upper_bucket_count + // + //Maximum fallbacks to the highest possible value + typename Container::size_type sz = Container::suggested_upper_bucket_count(size_type(-1)); + BOOST_TEST( sz > size_type(-1)/2 ); + //In the rest of cases the upper bound is returned + sz = Container::suggested_upper_bucket_count(size_type(-1)/2); + BOOST_TEST( sz >= size_type(-1)/2 ); + sz = Container::suggested_upper_bucket_count(size_type(-1)/4); + BOOST_TEST( sz >= size_type(-1)/4 ); + sz = Container::suggested_upper_bucket_count(0); + BOOST_TEST( sz > 0 ); + // + //suggested_lower_bucket_count + // + sz = Container::suggested_lower_bucket_count(size_type(-1)); + BOOST_TEST( sz <= size_type(-1) ); + //In the rest of cases the lower bound is returned + sz = Container::suggested_lower_bucket_count(size_type(-1)/2); + BOOST_TEST( sz <= size_type(-1)/2 ); + sz = Container::suggested_lower_bucket_count(size_type(-1)/4); + BOOST_TEST( sz <= size_type(-1)/4 ); + //Minimum fallbacks to the lowest possible value + sz = Container::suggested_upper_bucket_count(0); + BOOST_TEST( sz > 0 ); +} + +template< class Container, class Data > +void test_common_unordered_and_associative_container(Container & c, Data & d, boost::intrusive::detail::false_ unordered) +{ + (void)unordered; + typedef typename Container::size_type size_type; + typedef typename Container::key_of_value key_of_value; + typedef typename Container::iterator iterator; + typedef typename Container::const_iterator const_iterator; + + assert( d.size() > 2 ); + + c.clear(); + typename Container::reference r = *d.begin(); + c.insert(d.begin(), ++d.begin()); + BOOST_TEST( &*Container::s_iterator_to(*c.begin()) == &r ); + BOOST_TEST( &*Container::s_iterator_to(*c.cbegin()) == &r ); + + c.clear(); + c.insert(d.begin(), d.end()); + { + Container const &cc = c; + for( typename Data::const_iterator di = d.begin(), de = d.end(); + di != de; ++di ) + { + BOOST_TEST( cc.find(key_of_value()(*di), c.key_comp()) != cc.end() ); + std::pair<const_iterator, const_iterator> rdi = cc.equal_range(key_of_value()(*di), c.key_comp()); + BOOST_TEST(rdi.first != rdi.second); + BOOST_TEST(size_type(boost::intrusive::iterator_distance(rdi.first, rdi.second)) == cc.count(key_of_value()(*di), c.key_comp())); + } + + for( iterator ci = c.begin(), ce = c.end(); ci != ce; ) + { + BOOST_TEST( c.find(key_of_value()(*ci)) != c.end() ); + std::pair<iterator, iterator> rci = c.equal_range(key_of_value()(*ci), c.key_comp()); + BOOST_TEST(rci.first != rci.second); + size_type const sc = c.count(key_of_value()(*ci), c.key_comp()); + BOOST_TEST(size_type(boost::intrusive::iterator_distance(rci.first, rci.second)) == sc); + BOOST_TEST(sc == c.erase(key_of_value()(*ci), c.key_comp())); + ci = rci.second; + } + BOOST_TEST(c.empty()); + } + + c.clear(); + c.insert(d.begin(), d.end()); + + typename Data::const_iterator db = d.begin(); + typename Data::const_iterator da = db++; + + size_type old_size = c.size(); + + c.erase(key_of_value()(*da), c.key_comp()); + BOOST_TEST( c.size() == old_size-1 ); + //This should not erase any + size_type second_erase = c.erase_and_dispose( key_of_value()(*da), c.key_comp(), detail::null_disposer() ); + BOOST_TEST( second_erase == 0 ); + + BOOST_TEST( c.count(key_of_value()(*da), c.key_comp()) == 0 ); + BOOST_TEST( c.count(key_of_value()(*db), c.key_comp()) != 0 ); + BOOST_TEST( c.find(key_of_value()(*da), c.key_comp()) == c.end() ); + BOOST_TEST( c.find(key_of_value()(*db), c.key_comp()) != c.end() ); + BOOST_TEST( c.equal_range(key_of_value()(*db), c.key_comp()).first != c.end() ); + c.clear(); + BOOST_TEST( c.equal_range(key_of_value()(*da), c.key_comp()).first == c.end() ); +} + +template< class Container, class Data > +void test_common_unordered_and_associative_container(Container & c, Data & d) +{ + typedef typename Container::size_type size_type; + typedef typename Container::key_of_value key_of_value; + typedef typename Container::iterator iterator; + typedef typename Container::const_iterator const_iterator; + + { + assert( d.size() > 2 ); + + c.clear(); + typename Container::reference r = *d.begin(); + c.insert(d.begin(), ++d.begin()); + BOOST_TEST( &*c.iterator_to(*c.begin()) == &r ); + BOOST_TEST( &*c.iterator_to(*c.cbegin()) == &r ); + + c.clear(); + c.insert(d.begin(), d.end()); + + Container const &cc = c; + for( typename Data::const_iterator di = d.begin(), de = d.end(); + di != de; ++di ) + { + BOOST_TEST( cc.find(key_of_value()(*di)) != cc.end() ); + std::pair<const_iterator, const_iterator> rdi = cc.equal_range(key_of_value()(*di)); + BOOST_TEST(rdi.first != rdi.second); + BOOST_TEST(size_type(boost::intrusive::iterator_distance(rdi.first, rdi.second)) == cc.count(key_of_value()(*di))); + } + + for( iterator ci = c.begin(), ce = c.end(); ci != ce; ) + { + BOOST_TEST( c.find(key_of_value()(*ci)) != c.end() ); + std::pair<iterator, iterator> rci = c.equal_range(key_of_value()(*ci)); + BOOST_TEST(rci.first != rci.second); + size_type const sc = c.count(key_of_value()(*ci)); + BOOST_TEST(size_type(boost::intrusive::iterator_distance(rci.first, rci.second)) == sc); + BOOST_TEST(sc == c.erase(key_of_value()(*ci))); + ci = rci.second; + } + BOOST_TEST(c.empty()); + } + { + c.clear(); + c.insert(d.begin(), d.end()); + + typename Data::const_iterator db = d.begin(); + typename Data::const_iterator da = db++; + + size_type old_size = c.size(); + + c.erase(key_of_value()(*da)); + BOOST_TEST( c.size() == old_size-1 ); + //This should erase nothing + size_type second_erase = c.erase_and_dispose( key_of_value()(*da), detail::null_disposer() ); + BOOST_TEST( second_erase == 0 ); + + BOOST_TEST( c.count(key_of_value()(*da)) == 0 ); + BOOST_TEST( c.count(key_of_value()(*db)) != 0 ); + + BOOST_TEST( c.find(key_of_value()(*da)) == c.end() ); + BOOST_TEST( c.find(key_of_value()(*db)) != c.end() ); + + BOOST_TEST( c.equal_range(key_of_value()(*db)).first != c.end() ); + BOOST_TEST( c.equal_range(key_of_value()(*da)).first == c.equal_range(key_of_value()(*da)).second ); + } + { + c.clear(); + c.insert( d.begin(), d.end() ); + size_type orig_size = c.size(); + Container move_c(::boost::move(c)); + BOOST_TEST(orig_size == move_c.size()); + BOOST_TEST( c.empty()); + for( typename Data::const_iterator di = d.begin(), de = d.end(); + di != de; ++di ) + { BOOST_TEST( move_c.find(key_of_value()(*di)) != move_c.end() ); } + + c = ::boost::move(move_c); + for( typename Data::const_iterator di = d.begin(), de = d.end(); + di != de; ++di ) + { BOOST_TEST( c.find(key_of_value()(*di)) != c.end() ); } + BOOST_TEST( move_c.empty()); + } + typedef detail::bool_<is_unordered<Container>::value> enabler; + test_common_unordered_and_associative_container(c, d, enabler()); +} + +template< class Container, class Data > +void test_associative_container_invariants(Container & c, Data & d) +{ + typedef typename Container::const_iterator const_iterator; + typedef typename Container::key_of_value key_of_value; + for( typename Data::const_iterator di = d.begin(), de = d.end(); + di != de; ++di) + { + const_iterator ci = c.find(key_of_value()(*di)); + BOOST_TEST( ci != c.end() ); + BOOST_TEST( ! c.value_comp()(*ci, *di) ); + BOOST_TEST( ! c.key_comp()(key_of_value()(*ci), key_of_value()(*di)) ); + const_iterator cil = c.lower_bound(key_of_value()(*di)); + const_iterator ciu = c.upper_bound(key_of_value()(*di)); + std::pair<const_iterator, const_iterator> er = c.equal_range(key_of_value()(*di)); + BOOST_TEST( cil == er.first ); + BOOST_TEST( ciu == er.second ); + if(ciu != c.end()){ + BOOST_TEST( c.value_comp()(*cil, *ciu) ); + BOOST_TEST( c.key_comp()(key_of_value()(*cil), key_of_value()(*ciu)) ); + } + if(c.count(key_of_value()(*di)) > 1){ + const_iterator ci_next = cil; ++ci_next; + for( ; ci_next != ciu; ++cil, ++ci_next){ + BOOST_TEST( !c.value_comp()(*ci_next, *cil) ); + BOOST_TEST( !c.key_comp()(key_of_value()(*ci_next), key_of_value()(*cil)) ); + } + } + } +} + +template< class Container, class Data > +void test_associative_container(Container & c, Data & d) +{ + assert( d.size() > 2 ); + + c.clear(); + c.insert(d.begin(),d.end()); + + test_associative_container_invariants(c, d); + + const Container & cr = c; + + test_associative_container_invariants(cr, d); +} + +template< class Container, class Data > +void test_unordered_associative_container_invariants(Container & c, Data & d) +{ + typedef typename Container::size_type size_type; + typedef typename Container::const_iterator const_iterator; + typedef typename Container::key_of_value key_of_value; + + for( typename Data::const_iterator di = d.begin(), de = d.end() ; + di != de ; ++di ){ + const_iterator i = c.find(key_of_value()(*di)); + size_type nb = c.bucket(key_of_value()(*i)); + size_type bucket_elem = boost::intrusive::iterator_distance(c.begin(nb), c.end(nb)); + BOOST_TEST( bucket_elem == c.bucket_size(nb) ); + BOOST_TEST( &*c.local_iterator_to(*c.find(key_of_value()(*di))) == &*i ); + BOOST_TEST( &*c.local_iterator_to(*const_cast<const Container &>(c).find(key_of_value()(*di))) == &*i ); + BOOST_TEST( &*Container::s_local_iterator_to(*c.find(key_of_value()(*di))) == &*i ); + BOOST_TEST( &*Container::s_local_iterator_to(*const_cast<const Container &>(c).find(key_of_value()(*di))) == &*i ); + std::pair<const_iterator, const_iterator> er = c.equal_range(key_of_value()(*di)); + size_type cnt = boost::intrusive::iterator_distance(er.first, er.second); + BOOST_TEST( cnt == c.count(key_of_value()(*di))); + if(cnt > 1){ + const_iterator n = er.first; + i = n++; + const_iterator e = er.second; + for(; n != e; ++i, ++n){ + BOOST_TEST( c.key_eq()(key_of_value()(*i), key_of_value()(*n)) ); + BOOST_TEST( (c.hash_function()(key_of_value()(*i))) == (c.hash_function()(key_of_value()(*n))) ); + } + } + } + + size_type blen = c.bucket_count(); + size_type total_objects = 0; + for(size_type i = 0; i < blen; ++i){ + total_objects += c.bucket_size(i); + } + BOOST_TEST( total_objects == c.size() ); +} + +template< class Container, class Data > +void test_unordered_associative_container(Container & c, Data & d) +{ + c.clear(); + c.insert( d.begin(), d.end() ); + + test_unordered_associative_container_invariants(c, d); + + const Container & cr = c; + + test_unordered_associative_container_invariants(cr, d); +} + +template< class Container, class Data > +void test_unique_container(Container & c, Data & d) +{ + //typedef typename Container::value_type value_type; + c.clear(); + c.insert(d.begin(),d.end()); + typename Container::size_type old_size = c.size(); + //value_type v(*d.begin()); + //c.insert(v); + Data d2(1); + (&d2.front())->value_ = (&d.front())->value_; + c.insert(d2.front()); + BOOST_TEST( c.size() == old_size ); + c.clear(); +} + +template< class Container, class Data > +void test_non_unique_container(Container & c, Data & d) +{ + //typedef typename Container::value_type value_type; + c.clear(); + c.insert(d.begin(),d.end()); + typename Container::size_type old_size = c.size(); + //value_type v(*d.begin()); + //c.insert(v); + Data d2(1); + (&d2.front())->value_ = (&d.front())->value_; + c.insert(d2.front()); + BOOST_TEST( c.size() == (old_size+1) ); + c.clear(); +} + +template< class Container, class Data > +void test_maybe_unique_container(Container & c, Data & d, detail::false_)//is_unique +{ test_unique_container(c, d); } + +template< class Container, class Data > +void test_maybe_unique_container(Container & c, Data & d, detail::true_)//!is_unique +{ test_non_unique_container(c, d); } + +template< class RandomIt > +void random_shuffle( RandomIt first, RandomIt last ) +{ + typedef typename boost::intrusive::iterator_traits<RandomIt>::difference_type difference_type; + difference_type n = last - first; + for (difference_type i = n-1; i > 0; --i) { + difference_type j = std::rand() % (i+1); + if(j != i) { + boost::adl_move_swap(first[i], first[j]); + } + } +} + +}}} + +#endif //#ifndef BOOST_INTRUSIVE_TEST_CONTAINER_HPP diff --git a/src/boost/libs/intrusive/test/test_macros.hpp b/src/boost/libs/intrusive/test/test_macros.hpp new file mode 100644 index 00000000..1f72d978 --- /dev/null +++ b/src/boost/libs/intrusive/test/test_macros.hpp @@ -0,0 +1,81 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2013 +// +// 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_MACROS_HPP +#define BOOST_INTRUSIVE_TEST_TEST_MACROS_HPP + +#include <boost/intrusive/intrusive_fwd.hpp> +#include <algorithm> //std::unique + +namespace boost{ +namespace intrusive{ +namespace test{ + +template <class T> +struct is_multikey_true +{ + typedef char yes_type; + template<bool IsMultikey> + struct two { yes_type _[1+IsMultikey]; }; + template <class U> static yes_type test(...); + template <class U> static two<U::is_multikey>test(int); + static const bool value = sizeof(test<T>(0)) != sizeof(yes_type); +}; + +} //namespace test{ + +template<class It1, class It2> +bool test_equal(It1 f1, It1 l1, It2 f2) +{ + while(f1 != l1){ + if(*f1 != *f2){ + return false; + } + ++f1; + ++f2; + } + return true; +} + +#define TEST_INTRUSIVE_SEQUENCE( INTVALUES, ITERATOR )\ +{ \ + BOOST_TEST (boost::intrusive::test_equal(&INTVALUES[0], &INTVALUES[0] + sizeof(INTVALUES)/sizeof(INTVALUES[0]), ITERATOR) ); \ +} + +#define TEST_INTRUSIVE_SEQUENCE_EXPECTED( EXPECTEDVECTOR, ITERATOR )\ +{ \ + BOOST_TEST (boost::intrusive::test_equal(EXPECTEDVECTOR.begin(), EXPECTEDVECTOR.end(), ITERATOR) ); \ +} + +namespace test{ + +template<class Container, class Vector> +void test_intrusive_maybe_unique(const Container &c, Vector &v) +{ + if(!is_multikey_true<Container>::value) + v.erase(std::unique(v.begin(), v.end()), v.end()); + BOOST_TEST (boost::intrusive::test_equal(v.begin(), v.end(), c.begin()) ); +} + +} //namespace test{ + +#define TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE(INTVALUES, CONTAINER)\ +{\ + boost::container::vector<int>v(&INTVALUES[0], &INTVALUES[0] + sizeof(INTVALUES)/sizeof(INTVALUES[0]));\ + boost::intrusive::test::test_intrusive_maybe_unique(CONTAINER, v);\ +}\ +// + +} //namespace boost{ +} //namespace intrusive{ + +#endif diff --git a/src/boost/libs/intrusive/test/treap_multiset_test.cpp b/src/boost/libs/intrusive/test/treap_multiset_test.cpp new file mode 100644 index 00000000..79d6e49b --- /dev/null +++ b/src/boost/libs/intrusive/test/treap_multiset_test.cpp @@ -0,0 +1,157 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2013 +// +// 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 "itestvalue.hpp" +#include "bptr_value.hpp" +#include "smart_ptr.hpp" +#include "bs_test_common.hpp" +#include "generic_multiset_test.hpp" +#include <boost/intrusive/treap_set.hpp> + +using namespace boost::intrusive; + +template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map > +struct rebinder +{ + typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef treap_multiset + < typename common_t::value_type + , value_traits<ValueTraits> + , constant_time_size<ConstantTimeSize> + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , typename common_t::prio_of_value_opt + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value)); + }; +}; + +enum HookType +{ + Base, + Member, + NonMember +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type> +class test_main_template; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > 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 + < rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //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 + < rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //nonmember + test::test_generic_multiset + < rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map> + >::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<allocator_type> bounded_scope; (void)bounded_scope; + test::test_generic_multiset + < 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<void*, false, false, false, Base>::execute(); + //test_main_template<void*, false, false, true>::execute(); + test_main_template<void*, false, true, false, Member>::execute(); + //test_main_template<void*, false, true, true>::execute(); + test_main_template<void*, true, false, false, Base>::execute(); + //test_main_template<void*, true, false, true>::execute(); + test_main_template<void*, true, true, false, Member>::execute(); + test_main_template<void*, true, true, true, NonMember>::execute(); + + //smart_ptr + //test_main_template<smart_ptr<void>, false, false, false>::execute(); + test_main_template<smart_ptr<void>, false, false, true, Base>::execute(); + //test_main_template<smart_ptr<void>, false, true, false>::execute(); + test_main_template<smart_ptr<void>, false, true, true, Member>::execute(); + //test_main_template<smart_ptr<void>, true, false, false>::execute(); + test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute(); + //test_main_template<smart_ptr<void>, true, true, false>::execute(); + //test_main_template<smart_ptr<void>, 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/src/boost/libs/intrusive/test/treap_set_test.cpp b/src/boost/libs/intrusive/test/treap_set_test.cpp new file mode 100644 index 00000000..f7987777 --- /dev/null +++ b/src/boost/libs/intrusive/test/treap_set_test.cpp @@ -0,0 +1,156 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-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 "itestvalue.hpp" +#include "bptr_value.hpp" +#include "smart_ptr.hpp" +#include "bs_test_common.hpp" +#include "generic_set_test.hpp" +#include <boost/intrusive/treap_set.hpp> + +using namespace boost::intrusive; + +template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map > +struct rebinder +{ + typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef treap_set + < typename common_t::value_type + , value_traits<ValueTraits> + , constant_time_size<ConstantTimeSize> + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , typename common_t::prio_of_value_opt + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value)); + }; +}; + +enum HookType +{ + Base, + Member, + NonMember +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type> +class test_main_template; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > 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 + < rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //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 + < rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map> + >::test_all(); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember> +{ + public: + static void execute() + { + typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t; + //nonmember + test::test_generic_set + < rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map> + >::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<allocator_type> bounded_scope; (void)bounded_scope; + test::test_generic_set + < 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<void*, false, false, false, Base>::execute(); + //test_main_template<void*, false, false, true>::execute(); + test_main_template<void*, false, true, false, Member>::execute(); + //test_main_template<void*, false, true, true>::execute(); + test_main_template<void*, true, false, false, Base>::execute(); + //test_main_template<void*, true, false, true>::execute(); + test_main_template<void*, true, true, false, Member>::execute(); + test_main_template<void*, true, true, true, NonMember>::execute(); + + //smart_ptr + //test_main_template<smart_ptr<void>, false, false, false>::execute(); + test_main_template<smart_ptr<void>, false, false, true, Base>::execute(); + //test_main_template<smart_ptr<void>, false, true, false>::execute(); + test_main_template<smart_ptr<void>, false, true, true, Member>::execute(); + //test_main_template<smart_ptr<void>, true, false, false>::execute(); + test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute(); + //test_main_template<smart_ptr<void>, true, true, false>::execute(); + //test_main_template<smart_ptr<void>, 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/src/boost/libs/intrusive/test/unordered_multiset_test.cpp b/src/boost/libs/intrusive/test/unordered_multiset_test.cpp new file mode 100644 index 00000000..af872b3c --- /dev/null +++ b/src/boost/libs/intrusive/test/unordered_multiset_test.cpp @@ -0,0 +1,167 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (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 <boost/intrusive/unordered_set.hpp> +#include <boost/intrusive/pointer_traits.hpp> +#include <boost/intrusive/detail/iterator.hpp> +#include "itestvalue.hpp" +#include "smart_ptr.hpp" +#include "common_functors.hpp" +#include <vector> +#include <algorithm> //std::sort +#include <set> +#include <boost/detail/lightweight_test.hpp> + +#include "test_macros.hpp" +#include "test_container.hpp" +#include "unordered_test_common.hpp" +#include "unordered_test.hpp" + +using namespace boost::intrusive; + +template < class ValueTraits, bool ConstantTimeSize, bool CacheBegin, bool CompareHash, bool Incremental, bool Map, bool DefaultHolder > +struct rebinder +{ + typedef unordered_rebinder_common<ValueTraits, DefaultHolder, Map> common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef unordered_multiset + < typename common_t::value_type + , value_traits<ValueTraits> + , constant_time_size<ConstantTimeSize> + , cache_begin<CacheBegin> + , compare_hash<CompareHash> + , incremental<Incremental> + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value)); + BOOST_STATIC_ASSERT((boost::intrusive::test::is_multikey_true<type>::value)); + }; +}; + +enum HookType +{ + Base, + Member, + NonMember +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type> +class test_main_template; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base> +{ + public: + static void execute() + { + typedef testvalue<unordered_hooks<VoidPointer> > 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<VoidPointer> > 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<true> + >::type base_hook_t; + test::test_unordered + < //cache_begin, compare_hash, incremental + rebinder<base_hook_t, ConstantTimeSize, ConstantTimeSize, !ConstantTimeSize, !!ConstantTimeSize, Map, DefaultHolder> + >::test_all(data); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member> +{ + public: + static void execute() + { + typedef testvalue<unordered_hooks<VoidPointer> > 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<VoidPointer> > testval_traits_t; + //member + typedef typename detail::if_c + < ConstantTimeSize + , typename testval_traits_t::member_value_traits //optimize_multikey<true> + , typename testval_traits_t::auto_member_value_traits //store_hash<true>, optimize_multikey<true> + >::type member_hook_t; + test::test_unordered + < //cache_begin, compare_hash, incremental + rebinder<member_hook_t, ConstantTimeSize, false, !ConstantTimeSize, false, !ConstantTimeSize, DefaultHolder> + >::test_all(data); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember> + +{ + public: + static void execute() + { + typedef testvalue<unordered_hooks<VoidPointer> > 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<VoidPointer> > testval_traits_t; + //nonmember + test::test_unordered + < //cache_begin, compare_hash, incremental + rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, false, false, false, Map, DefaultHolder> + >::test_all(data); + } +}; + +int main() +{ + //VoidPointer x ConstantTimeSize x Map x DefaultHolder + + //void pointer + test_main_template<void*, false, false, false, Base>::execute(); + test_main_template<void*, false, true, false, Member>::execute(); + test_main_template<void*, true, false, false, NonMember>::execute(); + test_main_template<void*, true, true, false, Base>::execute(); + + //smart_ptr + test_main_template<smart_ptr<void>, false, false, false, Member>::execute(); + test_main_template<smart_ptr<void>, false, true, false, NonMember>::execute(); + test_main_template<smart_ptr<void>, true, false, false, Base>::execute(); + test_main_template<smart_ptr<void>, true, true, false, Member>::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/src/boost/libs/intrusive/test/unordered_set_test.cpp b/src/boost/libs/intrusive/test/unordered_set_test.cpp new file mode 100644 index 00000000..60e8d368 --- /dev/null +++ b/src/boost/libs/intrusive/test/unordered_set_test.cpp @@ -0,0 +1,167 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (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 <boost/intrusive/unordered_set.hpp> +#include <boost/intrusive/pointer_traits.hpp> +#include <boost/intrusive/detail/iterator.hpp> +#include "itestvalue.hpp" +#include "smart_ptr.hpp" +#include "common_functors.hpp" +#include <vector> +#include <set> +#include <boost/detail/lightweight_test.hpp> +#include "test_macros.hpp" +#include "test_container.hpp" +#include "unordered_test_common.hpp" +#include "unordered_test.hpp" + +using namespace boost::intrusive; + +template < class ValueTraits, bool ConstantTimeSize, bool CacheBegin, bool CompareHash, bool Incremental, bool Map, bool DefaultHolder > +struct rebinder +{ + typedef unordered_rebinder_common<ValueTraits, DefaultHolder, Map> common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; + + template < class Option1 =void + , class Option2 =void + > + struct container + { + typedef unordered_set + < typename common_t::value_type + , value_traits<ValueTraits> + , constant_time_size<ConstantTimeSize> + , cache_begin<CacheBegin> + , compare_hash<CompareHash> + , incremental<Incremental> + , typename common_t::holder_opt + , typename common_t::key_of_value_opt + , size_type<unsigned short> + , Option1 + , Option2 + > type; + BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value)); + BOOST_STATIC_ASSERT((!boost::intrusive::test::is_multikey_true<type>::value)); + }; +}; + +enum HookType +{ + Base, + Member, + NonMember +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type> +class test_main_template; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base> +{ + public: + static void execute() + { + typedef testvalue<unordered_hooks<VoidPointer> > 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<VoidPointer> > 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<true> + >::type base_hook_t; + test::test_unordered + < //cache_begin, compare_hash, incremental + rebinder<base_hook_t, ConstantTimeSize, ConstantTimeSize, !ConstantTimeSize, !!ConstantTimeSize, Map, DefaultHolder> + >::test_all(data); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member> +{ + public: + static void execute() + { + typedef testvalue<unordered_hooks<VoidPointer> > 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<VoidPointer> > testval_traits_t; + //member + typedef typename detail::if_c + < ConstantTimeSize + , typename testval_traits_t::member_value_traits //optimize_multikey<true> + , typename testval_traits_t::auto_member_value_traits //store_hash<true>, optimize_multikey<true> + >::type member_hook_t; + test::test_unordered + < //cache_begin, compare_hash, incremental + rebinder<member_hook_t, ConstantTimeSize, false, !ConstantTimeSize, false, !ConstantTimeSize, DefaultHolder> + >::test_all(data); + } +}; + +template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map> +class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember> + +{ + public: + static void execute() + { + typedef testvalue<unordered_hooks<VoidPointer> > 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<VoidPointer> > testval_traits_t; + //nonmember + test::test_unordered + < //cache_begin, compare_hash, incremental + rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, false, false, false, Map, DefaultHolder> + >::test_all(data); + } +}; + +int main() +{ + //VoidPointer x ConstantTimeSize x Map x DefaultHolder + + //void pointer + test_main_template<void*, false, false, false, Base>::execute(); + test_main_template<void*, false, true, false, Member>::execute(); + test_main_template<void*, true, false, false, NonMember>::execute(); + test_main_template<void*, true, true, false, Base>::execute(); + + //smart_ptr + test_main_template<smart_ptr<void>, false, false, false, Member>::execute(); + test_main_template<smart_ptr<void>, false, true, false, NonMember>::execute(); + test_main_template<smart_ptr<void>, true, false, false, Base>::execute(); + test_main_template<smart_ptr<void>, true, true, false, Member>::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/src/boost/libs/intrusive/test/unordered_test.hpp b/src/boost/libs/intrusive/test/unordered_test.hpp new file mode 100644 index 00000000..29bd7056 --- /dev/null +++ b/src/boost/libs/intrusive/test/unordered_test.hpp @@ -0,0 +1,751 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (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 <boost/intrusive/pointer_traits.hpp> +#include <boost/intrusive/detail/iterator.hpp> +#include "common_functors.hpp" +#include <vector> +#include <algorithm> //std::sort +#include <set> +#include <boost/detail/lightweight_test.hpp> + +#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<class ContainerDefiner> +struct test_unordered +{ + typedef typename ContainerDefiner::value_cont_type value_cont_type; + + 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<class ContainerDefiner> +void test_unordered<ContainerDefiner>::test_all (value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + typedef typename unordered_type::bucket_traits bucket_traits; + typedef typename unordered_type::bucket_ptr bucket_ptr; + { + typename unordered_type::bucket_type buckets [BucketSize]; + unordered_type testset + (bucket_traits(pointer_traits<bucket_ptr>::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_<boost::intrusive::test::is_multikey_true + <unordered_type>::value> select_t; + test::test_maybe_unique_container(testset, values, select_t()); + } + { + value_cont_type vals(BucketSize); + for (int i = 0; i < (int)BucketSize; ++i) + (&vals[i])->value_ = i; + typename unordered_type::bucket_type buckets [BucketSize]; + unordered_type testset(bucket_traits( + pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize)); + testset.insert(vals.begin(), vals.end()); + test::test_iterator_forward(testset); + } + test_sort(values); + test_insert(values, detail::bool_<boost::intrusive::test::is_multikey_true<unordered_type>::value>()); + test_swap(values); + test_rehash(values, detail::bool_<unordered_type::incremental>()); + test_find(values); + test_impl(); + test_clone(values); +} + +//test case due to an error in tree implementation: +template<class ContainerDefiner> +void test_unordered<ContainerDefiner>::test_impl() +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + typedef typename unordered_type::bucket_traits bucket_traits; + typedef typename unordered_type::bucket_ptr bucket_ptr; + + 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<bucket_ptr>::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<class ContainerDefiner> +void test_unordered<ContainerDefiner>::test_sort(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + typedef typename unordered_type::bucket_traits bucket_traits; + typedef typename unordered_type::bucket_ptr bucket_ptr; + + typename unordered_type::bucket_type buckets [BucketSize]; + unordered_type testset1 + (values.begin(), values.end(), bucket_traits + (pointer_traits<bucket_ptr>::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<class ContainerDefiner> +void test_unordered<ContainerDefiner>::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; + typedef typename unordered_set_type::key_of_value key_of_value; + + typename unordered_set_type::bucket_type buckets [BucketSize]; + unordered_set_type testset(bucket_traits( + pointer_traits<typename unordered_set_type::bucket_ptr>:: + pointer_to(buckets[0]), BucketSize)); + testset.insert(&values[0] + 2, &values[0] + 5); + + typename unordered_set_type::insert_commit_data commit_data; + BOOST_TEST ((!testset.insert_check(key_of_value()(values[2]), commit_data).second)); + BOOST_TEST (( testset.insert_check(key_of_value()(values[0]), commit_data).second)); + + 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<class ContainerDefiner> +void test_unordered<ContainerDefiner>::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::bucket_ptr bucket_ptr; + 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<bucket_ptr>::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<bucket_ptr>::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<bucket_ptr>::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<bucket_ptr>::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)); + } + } + } + { + const unsigned int LoadFactor = 3; + const unsigned int NumIterations = BucketSize*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; + } + + typename unordered_type::bucket_type buckets [BucketSize]; + bucket_traits btraits(pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize); + + 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.data() + , random_init.data() + random_init.size() + , btraits); + + 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<class ContainerDefiner> +void test_unordered<ContainerDefiner>::test_swap(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + + typedef typename unordered_type::bucket_traits bucket_traits; + typedef typename unordered_type::bucket_ptr bucket_ptr; + 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<bucket_ptr>::pointer_to(buckets[0]), BucketSize)); + unordered_type testset2(bucket_traits( + pointer_traits<bucket_ptr>::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<class ContainerDefiner> +void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, detail::true_) +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + + typedef typename unordered_type::bucket_traits bucket_traits; + typedef typename unordered_type::bucket_ptr bucket_ptr; + //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<bucket_ptr>:: + 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<bucket_ptr>:: + 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<bucket_ptr>:: + 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<bucket_ptr>:: + 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<bucket_ptr>:: + 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 ); } + + //Shrink rehash + testset1.rehash(bucket_traits( + pointer_traits<bucket_ptr>:: + 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 ); } + + //Shrink rehash again + testset1.rehash(bucket_traits( + pointer_traits<bucket_ptr>:: + 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 ); } + + //Growing rehash + testset1.rehash(bucket_traits( + pointer_traits<bucket_ptr>:: + pointer_to(buckets1[0]), BucketSize)); + + //Full rehash (no effects) + testset1.full_rehash(); + { 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<class ContainerDefiner> +void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, detail::false_) +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + + typedef typename unordered_type::bucket_traits bucket_traits; + typedef typename unordered_type::bucket_ptr bucket_ptr; + + 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<bucket_ptr>:: + 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<bucket_ptr>::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<bucket_ptr>::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<bucket_ptr>::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<bucket_ptr>::pointer_to(buckets3[0]), BucketSize*2)); + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + + //Full rehash (no effects) + testset1.full_rehash(); + { 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<class ContainerDefiner> +void test_unordered<ContainerDefiner>::test_find(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + typedef typename unordered_type::value_type value_type; + + typedef typename unordered_type::bucket_traits bucket_traits; + typedef typename unordered_type::bucket_ptr bucket_ptr; + typedef typename unordered_type::key_of_value key_of_value; + const bool is_multikey = boost::intrusive::test::is_multikey_true<unordered_type>::value; + + typename unordered_type::bucket_type buckets[BucketSize]; + unordered_type testset(values.begin(), values.end(), bucket_traits( + pointer_traits<bucket_ptr>::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<iterator,iterator> 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<class ContainerDefiner> +void test_unordered<ContainerDefiner>::test_clone(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type unordered_type; + typedef typename unordered_type::value_type value_type; + typedef std::multiset<value_type> std_multiset_t; + + typedef typename unordered_type::bucket_traits bucket_traits; + typedef typename unordered_type::bucket_ptr bucket_ptr; + + { + //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<bucket_ptr>::pointer_to(buckets1[0]), BucketSize)); + unordered_type testset2 (bucket_traits( + pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), BucketSize)); + + testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>()); + 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<value_type>()); + BOOST_TEST (testset2.empty()); + + testset2.clone_from(boost::move(testset1), test::new_nonconst_cloner<value_type>(), test::delete_disposer<value_type>()); + 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<value_type>()); + 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<bucket_ptr>::pointer_to(buckets1[0]), BucketSize*2)); + unordered_type testset2 (bucket_traits( + pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), BucketSize)); + + testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>()); + 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<value_type>()); + BOOST_TEST (testset2.empty()); + + testset2.clone_from(boost::move(testset1), test::new_nonconst_cloner<value_type>(), test::delete_disposer<value_type>()); + 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<value_type>()); + 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<bucket_ptr>::pointer_to(buckets1[0]), BucketSize)); + unordered_type testset2 (bucket_traits( + pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), BucketSize*2)); + + testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>()); + 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<value_type>()); + BOOST_TEST (testset2.empty()); + + testset2.clone_from(boost::move(testset1), test::new_nonconst_cloner<value_type>(), test::delete_disposer<value_type>()); + 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<value_type>()); + BOOST_TEST (testset2.empty()); + } +} + +} //namespace test{ +} //namespace intrusive{ +} //namespace boost{ diff --git a/src/boost/libs/intrusive/test/unordered_test_common.hpp b/src/boost/libs/intrusive/test/unordered_test_common.hpp new file mode 100644 index 00000000..385b39df --- /dev/null +++ b/src/boost/libs/intrusive/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 <boost/intrusive/unordered_set_hook.hpp> +#include <boost/intrusive/detail/mpl.hpp> +#include "bptr_value.hpp" +#include "test_common.hpp" + +namespace boost { +namespace intrusive { + +template<class VoidPointer> +struct unordered_hooks +{ + typedef unordered_set_base_hook<void_pointer<VoidPointer> > base_hook_type; + typedef unordered_set_base_hook + < link_mode<auto_unlink> + , void_pointer<VoidPointer> + , tag<void> + , store_hash<true> + > auto_base_hook_type; + + typedef unordered_set_member_hook + < void_pointer<VoidPointer> + , optimize_multikey<true> + > member_hook_type; + typedef unordered_set_member_hook + < link_mode<auto_unlink>, void_pointer<VoidPointer> + , store_hash<true> + , optimize_multikey<true> + > 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_type, BPtr_Value>::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<int_holder_key_of_value<value_type> >, void + >::type key_of_value_opt; +}; + +} //namespace intrusive { +} //namespace boost { + +#endif //BOOST_INTRUSIVE_TEST_UNORDERED_TEST_COMMON_HPP diff --git a/src/boost/libs/intrusive/test/virtual_base_test.cpp b/src/boost/libs/intrusive/test/virtual_base_test.cpp new file mode 100644 index 00000000..b1b25925 --- /dev/null +++ b/src/boost/libs/intrusive/test/virtual_base_test.cpp @@ -0,0 +1,100 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2013 +// +// 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 <boost/intrusive/list.hpp> +#include <boost/intrusive/slist.hpp> +#include <boost/intrusive/set.hpp> +#include <boost/intrusive/unordered_set.hpp> +#include <vector> + +using namespace boost::intrusive; + +struct VirtualBase +{ + virtual ~VirtualBase(){} +}; + +struct VirtualBase2 +{ + virtual ~VirtualBase2(){} +}; + +struct VirtualBase3 +{ +}; + +class NonVirtualBase + : public virtual VirtualBase + , public virtual VirtualBase2 +{ + protected: + NonVirtualBase() + : dummy() + {} + + //<- + const int *get_dummy() const { return dummy; } + //-> + + private: + int dummy[10]; +}; + +class MyClass + : public NonVirtualBase + , public virtual VirtualBase3 +{ + int int_; + + public: + list_member_hook<> list_hook_; + MyClass(int i = 0) + : int_(i) + {} + //<- + int get_int() const { return int_; } + //-> +}; + +//Define a list that will store MyClass using the public base hook +typedef member_hook< MyClass, list_member_hook<>, &MyClass::list_hook_ > MemberHook; +typedef list<MyClass, MemberHook> List; + +int main() +{ + #ifndef _MSC_VER + typedef std::vector<MyClass>::iterator VectIt; + typedef std::vector<MyClass>::reverse_iterator VectRit; + + //Create several MyClass objects, each one with a different value + std::vector<MyClass> values; + for(int i = 0; i < 100; ++i) values.push_back(MyClass(i)); + + List my_list; + + //Now insert them in the reverse order + //in the base hook intrusive list + for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it) + my_list.push_front(*it); + + //Now test lists + { + List::const_iterator list_it(my_list.cbegin()); + VectRit vect_it(values.rbegin()), vect_itend(values.rend()); + + //Test the objects inserted in the base hook list + for(; vect_it != vect_itend; ++vect_it, ++list_it) + if(&*list_it != &*vect_it) + return 1; + } + #endif + return 0; +} diff --git a/src/boost/libs/intrusive/test/voidptr_key_test.cpp b/src/boost/libs/intrusive/test/voidptr_key_test.cpp new file mode 100644 index 00000000..c6055999 --- /dev/null +++ b/src/boost/libs/intrusive/test/voidptr_key_test.cpp @@ -0,0 +1,94 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Andrey Semashev 2018. +// +// 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 <boost/intrusive/options.hpp> +#include <boost/intrusive/set.hpp> +#include <boost/intrusive/set_hook.hpp> +#include <boost/config.hpp> +#include <boost/core/lightweight_test.hpp> +#include <functional> // std::less + +// The test verifies that the set implementation does not use void* as auxiliary arguments for SFINAE +// in internal functions, which would make overload resolution ambiguous if user's key type is also void*. + +typedef boost::intrusive::set_base_hook< + boost::intrusive::link_mode< boost::intrusive::safe_link >, + boost::intrusive::tag< struct for_set_element_lookup_by_key >, + boost::intrusive::optimize_size< true > +> set_element_hook_t; + +struct set_element : + public set_element_hook_t +{ + struct order_by_key + { + typedef bool result_type; + + result_type operator() (set_element const& left, set_element const& right) const + { + return std::less< void* >()(left.m_key, right.m_key); + } + result_type operator() (void* left, set_element const& right) const + { + return std::less< void* >()(left, right.m_key); + } + result_type operator() (set_element const& left, void* right) const + { + return std::less< void* >()(left.m_key, right); + } + }; + + void* m_key; + + explicit set_element(void* key) : m_key(key) {} + + BOOST_DELETED_FUNCTION(set_element(set_element const&)) + BOOST_DELETED_FUNCTION(set_element& operator=(set_element const&)) +}; + +typedef boost::intrusive::set< + set_element, + boost::intrusive::base_hook< set_element_hook_t >, + boost::intrusive::compare< set_element::order_by_key >, + boost::intrusive::constant_time_size< true > +> set_t; + +void test_set() +{ + int v1 = 0, v2 = 1, v3 = 2; + set_element e1(&v1), e2(&v2), e3(&v3); + + set_t s; + s.insert(e1); + s.insert(e2); + + set_t::iterator it = s.find(e1); + BOOST_TEST(it != s.end() && &*it == &e1); + + it = s.find((void*)&v2, set_element::order_by_key()); + BOOST_TEST(it != s.end() && &*it == &e2); + + it = s.find(e3); + BOOST_TEST(it == s.end()); + + it = s.find((void*)&v3, set_element::order_by_key()); + BOOST_TEST(it == s.end()); + + s.clear(); +} + +int main() +{ + test_set(); + + return boost::report_errors(); +} |