diff --git a/test/avl_multiset_test.cpp b/test/avl_multiset_test.cpp index be6d3c2..c02f961 100644 --- a/test/avl_multiset_test.cpp +++ b/test/avl_multiset_test.cpp @@ -14,6 +14,7 @@ #include #include #include "itestvalue.hpp" +#include "bptr_value.hpp" #include "smart_ptr.hpp" #include "generic_multiset_test.hpp" @@ -60,6 +61,10 @@ struct hooks > nonhook_node_member_type; }; +// container generator with void node allocator +template < bool Default_Holder > +struct GetContainer_With_Holder +{ template< class ValueType , class Option1 =void , class Option2 =void @@ -74,8 +79,35 @@ struct GetContainer , Option3 > type; }; +}; -template +// container generator with standard (non-void) node allocator +template <> +struct GetContainer_With_Holder< false > +{ +template< class ValueType + , class Option1 =void + , class Option2 =void + , class Option3 =void + > +struct GetContainer +{ + // extract node type through options->value_traits->node_traits->node + typedef typename pack_options< avltree_defaults, Option1, Option2, Option3 >::type packed_options; + typedef typename detail::get_value_traits< ValueType, typename packed_options::proto_value_traits>::type value_traits; + typedef typename value_traits::node_traits::node node; + + typedef boost::intrusive::avl_multiset + < ValueType + , Option1 + , Option2 + , Option3 + , header_holder_type< pointer_holder< node > > + > type; +}; +}; + +template class test_main_template { public: @@ -88,7 +120,7 @@ class test_main_template < value_type , typename hooks::base_hook_type >::type - , GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_multiset < typename detail::get_member_value_traits < value_type @@ -97,21 +129,21 @@ class test_main_template , &value_type::node_ > >::type - , GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_multiset < nonhook_node_member_value_traits< value_type, typename hooks::nonhook_node_member_type, &value_type::nhn_member_, safe_link >, - GetContainer + GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); return 0; } }; -template -class test_main_template +template +class test_main_template { public: int operator()() @@ -123,7 +155,7 @@ class test_main_template < value_type , typename hooks::base_hook_type >::type - , GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_multiset < typename detail::get_member_value_traits @@ -133,14 +165,14 @@ class test_main_template , &value_type::node_ > >::type - , GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_multiset < typename detail::get_base_value_traits < value_type , typename hooks::auto_base_hook_type >::type - , GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_multiset < typename detail::get_member_value_traits @@ -150,18 +182,70 @@ class test_main_template , &value_type::auto_node_ > >::type - , GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); return 0; } }; +// container generator which ignores further parametrization, except for compare option +template < typename Value_Traits, bool Constant_Time_Size, typename Header_Holder > +struct Get_Preset_Container +{ + template < class + , class Option1 = void + , class Option2 = void + , class Option3 = void + > + struct GetContainer + { + // ignore further paramatrization except for the compare option + // notably ignore the size option (use preset) + typedef typename pack_options< avltree_defaults, Option1, Option2, Option3 >::type packed_options; + typedef typename packed_options::compare compare_option; + + typedef boost::intrusive::avl_multiset< typename Value_Traits::value_type, + value_traits< Value_Traits >, + constant_time_size< Constant_Time_Size >, + compare< compare_option >, + header_holder_type< Header_Holder > + > type; + }; +}; + +template < bool Constant_Time_Size > +struct test_main_template_bptr +{ + void operator () () + { + typedef BPtr_Value value_type; + typedef BPtr_Value_Traits< AVLTree_BPtr_Node_Traits > value_traits; + typedef Bounded_Allocator< value_type > allocator_type; + + allocator_type::init(); + test::test_generic_multiset< value_traits, + Get_Preset_Container< value_traits, Constant_Time_Size, + Bounded_Pointer_Holder< value_type > >::template GetContainer + >::test_all(); + assert(allocator_type::is_clear()); + allocator_type::destroy(); + } +}; + int main( int, char* [] ) { - test_main_template()(); - test_main_template, false>()(); - test_main_template()(); - test_main_template, true>()(); + // test (plain/smart pointers) x (nonconst/const size) x (void node allocator) + test_main_template()(); + test_main_template, false, true>()(); + test_main_template()(); + test_main_template, true, true>()(); + // test (plain pointers) x (nonconst/const size) x (standard node allocator) + test_main_template()(); + test_main_template()(); + // 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/test/avl_set_test.cpp b/test/avl_set_test.cpp index 36d0731..18d5b9d 100644 --- a/test/avl_set_test.cpp +++ b/test/avl_set_test.cpp @@ -13,6 +13,7 @@ #include #include #include "itestvalue.hpp" +#include "bptr_value.hpp" #include "smart_ptr.hpp" #include "generic_set_test.hpp" @@ -60,6 +61,10 @@ struct hooks > nonhook_node_member_type; }; +// container generator with void node allocator +template < bool Default_Holder > +struct GetContainer_With_Holder +{ template< class ValueType , class Option1 =void , class Option2 =void @@ -74,8 +79,35 @@ struct GetContainer , Option3 > type; }; +}; -template +// container generator with standard (non-void) node allocator +template <> +struct GetContainer_With_Holder< false > +{ +template< class ValueType + , class Option1 =void + , class Option2 =void + , class Option3 =void + > +struct GetContainer +{ + // extract node type through options->value_traits->node_traits->node + typedef typename pack_options< avltree_defaults, Option1, Option2, Option3 >::type packed_options; + typedef typename detail::get_value_traits< ValueType, typename packed_options::proto_value_traits>::type value_traits; + typedef typename value_traits::node_traits::node node; + + typedef boost::intrusive::avl_set + < ValueType + , Option1 + , Option2 + , Option3 + , header_holder_type< pointer_holder< node > > + > type; +}; +}; + +template class test_main_template { public: @@ -88,7 +120,7 @@ class test_main_template < value_type , typename hooks::base_hook_type >::type - , GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_set < typename detail::get_member_value_traits < value_type @@ -97,21 +129,21 @@ class test_main_template , &value_type::node_ > >::type - , GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_set < nonhook_node_member_value_traits< value_type, typename hooks::nonhook_node_member_type, &value_type::nhn_member_, safe_link >, - GetContainer + GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); return 0; } }; -template -class test_main_template +template +class test_main_template { public: int operator()() @@ -123,7 +155,7 @@ class test_main_template < value_type , typename hooks::base_hook_type >::type - , GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_set < typename detail::get_member_value_traits @@ -133,14 +165,14 @@ class test_main_template , &value_type::node_ > >::type - , GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_set < typename detail::get_base_value_traits < value_type , typename hooks::auto_base_hook_type >::type - , GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_set < typename detail::get_member_value_traits @@ -150,19 +182,70 @@ class test_main_template , &value_type::auto_node_ > >::type - , GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); return 0; } }; +// container generator which ignores further parametrization, except for compare option +template < typename Value_Traits, bool Constant_Time_Size, typename Header_Holder > +struct Get_Preset_Container +{ + template < class + , class Option1 = void + , class Option2 = void + , class Option3 = void + > + struct GetContainer + { + // ignore further paramatrization except for the compare option + // notably ignore the size option (use preset) + typedef typename pack_options< avltree_defaults, Option1, Option2, Option3 >::type packed_options; + typedef typename packed_options::compare compare_option; + + typedef boost::intrusive::avl_set< typename Value_Traits::value_type, + value_traits< Value_Traits >, + constant_time_size< Constant_Time_Size >, + compare< compare_option >, + header_holder_type< Header_Holder > + > type; + }; +}; + +template < bool Constant_Time_Size > +struct test_main_template_bptr +{ + void operator () () + { + typedef BPtr_Value value_type; + typedef BPtr_Value_Traits< AVLTree_BPtr_Node_Traits > value_traits; + typedef Bounded_Allocator< value_type > allocator_type; + + allocator_type::init(); + test::test_generic_set< value_traits, + Get_Preset_Container< value_traits, Constant_Time_Size, + Bounded_Pointer_Holder< value_type > >::template GetContainer + >::test_all(); + assert(allocator_type::is_clear()); + allocator_type::destroy(); + } +}; + int main( int, char* [] ) { - test_main_template()(); - test_main_template, false>()(); - test_main_template()(); - test_main_template, true>()(); + // test (plain/smart pointers) x (nonconst/const size) x (void node allocator) + test_main_template()(); + test_main_template, false, true>()(); + test_main_template()(); + test_main_template, true, true>()(); + // test (plain pointers) x (nonconst/const size) x (standard node allocator) + test_main_template()(); + test_main_template()(); + // 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/test/bounded_pointer.hpp b/test/bounded_pointer.hpp new file mode 100644 index 0000000..75828cc --- /dev/null +++ b/test/bounded_pointer.hpp @@ -0,0 +1,355 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (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 +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONST_CONVERSIONS(_type, _t) \ + operator const _type< typename boost::add_const< _t >::type >& () const \ + { return *reinterpret_cast< const _type< typename boost::add_const< _t >::type >* >(this); } \ + operator _type< typename boost::add_const< _t >::type >& () \ + { return *reinterpret_cast< _type< typename boost::add_const< _t >::type >* >(this); } \ + \ + const _type< typename boost::remove_const< _t >::type >& unconst() const \ + { return *reinterpret_cast< const _type< typename boost::remove_const< _t >::type >* >(this); } \ + _type< typename boost::remove_const< _t >::type >& unconst() \ + { return *reinterpret_cast< _type< typename boost::remove_const< _t >::type >* >(this); } + + +template < typename T > +class Bounded_Pointer; +template < typename T > +class Bounded_Reference; +template < typename T > +class Bounded_Allocator; + + +template < typename T > +class Bounded_Pointer +{ +public: + typedef typename boost::remove_const< T >::type mut_val_t; + typedef const mut_val_t const_val_t; + + template + struct rebind + { + typedef typename boost::mpl::if_< + boost::is_same< + typename boost::remove_const< U >::type, + typename boost::remove_const< T >::type >, + Bounded_Pointer< U >, + U* + >::type type; + }; + + Bounded_Pointer() : _offset(255) {} + Bounded_Pointer(const Bounded_Pointer& other) : _offset(other._offset) {} + Bounded_Pointer& operator = (const Bounded_Pointer& other) { _offset = other._offset; return *this; } + CONST_CONVERSIONS(Bounded_Pointer, T) + + static mut_val_t* base() + { + assert(Bounded_Allocator< mut_val_t >::inited()); + return &Bounded_Allocator< mut_val_t >::_base[0]; + } + + operator bool() const { return _offset != 255; } + + T* raw() const { return base() + _offset; } + Bounded_Reference< T > operator * () const { return Bounded_Reference< T >(*this); } + T* operator -> () const { return raw(); } + Bounded_Pointer& operator ++ () { ++_offset; return *this; } + Bounded_Pointer operator ++ (int) { Bounded_Pointer res(*this); ++(*this); return res; } + + template < typename U > + // typename boost::enable_if< boost::is_same< typename boost::remove_const< U >::type, + // typename boost::remove_const< T >::type >, int >::type = 42 > + bool operator == (const Bounded_Pointer< U >& rhs) const + { + return _offset == rhs._offset; + } + template < typename U > + // typename boost::enable_if< boost::is_same< typename boost::remove_const< U >::type, + // typename boost::remove_const< T >::type >, int >::type = 42 > + bool operator < (const Bounded_Pointer< U >& rhs) const + { + return _offset < rhs._offset; + } + + friend std::ostream& operator << (std::ostream& os, const Bounded_Pointer< T >& ptr) + { + os << static_cast< int >(ptr._offset); + return os; + } +private: + template friend class Bounded_Pointer; + friend class Bounded_Reference< T >; + friend class Bounded_Allocator< T >; + + uint8_t _offset; +}; // class Bounded_Pointer + +template < typename T > +class Bounded_Reference +{ +public: + typedef typename boost::remove_const< T >::type mut_val_t; + typedef const mut_val_t const_val_t; + + Bounded_Reference() : _offset(255) {} + Bounded_Reference(const Bounded_Reference& other) : _offset(other._offset) {} + CONST_CONVERSIONS(Bounded_Reference, T) + + T& raw() const { assert(_offset != 255); return *(Bounded_Pointer< T >::base() + _offset); } + operator T& () const { assert(_offset != 255); return raw(); } + Bounded_Pointer< T > operator & () const { assert(_offset != 255); Bounded_Pointer< T > res; res._offset = _offset; return res; } + + Bounded_Reference& operator = (const T& rhs) { assert(_offset != 255); raw() = rhs; return *this; } + Bounded_Reference& operator = (const Bounded_Reference& rhs) { assert(_offset != 255); raw() = rhs.raw(); return *this; } + + friend std::ostream& operator << (std::ostream& os, const Bounded_Reference< T >& ref) + { + os << "[bptr=" << static_cast< int >(ref._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) + { + std::swap(lhs._offset, rhs._offset); + } + +private: + friend class Bounded_Pointer< T >; + Bounded_Reference(Bounded_Pointer< T > bptr) : _offset(bptr._offset) { assert(_offset != 255); } + + uint8_t _offset; +}; // class Bounded_Reference + +template < typename T > +class Bounded_Allocator +{ +public: + typedef T value_type; + typedef Bounded_Pointer< T > pointer; + + pointer allocate(size_t n) + { + assert(inited()); + assert(n == 1); + pointer p; + uint8_t i; + for (i = 0; i < 255 and _in_use[i]; ++i); + assert(i < 255); + p._offset = i; + _in_use[p._offset] = true; + //std::clog << "allocating node " << static_cast< int >(p._offset) << "\n"; + return p; + } + void deallocate(pointer p, size_t n) + { + assert(inited()); + assert(n == 1); + assert(_in_use[p._offset]); + //std::clog << "deallocating node " << static_cast< int >(p._offset) << "\n"; + _in_use[p._offset] = false; + } + + // static methods + static void init() + { + assert(_in_use.empty()); + _in_use = std::vector< bool >(255, false); + // allocate non-constructed storage + _base = static_cast< T* >(::operator new [] (255 * sizeof(T))); + } + static bool inited() + { + return _in_use.size() == 255; + } + static bool is_clear() + { + assert(inited()); + for (uint8_t i = 0; i < 255; ++i) + { + if (_in_use[i]) + { + return false; + } + } + return true; + } + static void destroy() + { + // deallocate storage without destructors + ::operator delete [] (_base); + _in_use.clear(); + } + +private: + friend class Bounded_Pointer< T >; + friend class Bounded_Pointer< const T >; + static T* _base; + static std::vector< bool > _in_use; +}; // class Bounded_Allocator + +template < typename T > +T* Bounded_Allocator< T >::_base = NULL; + +template < typename T > +std::vector< bool > Bounded_Allocator< T >::_in_use; + + +template < typename T > +class Bounded_Reference_Cont + : public std::vector< Bounded_Reference< T > > +{ +private: + typedef T value_type; + typedef std::vector< Bounded_Reference< T > > Base; + typedef Bounded_Allocator< T > allocator_type; + typedef Bounded_Pointer< T > pointer; + +public: + Bounded_Reference_Cont(size_t n = 0) : Base(), _allocator() + { + for (size_t i = 0; i < n; ++i) + { + pointer p = _allocator.allocate(1); + new (p.raw()) value_type(); + Base::push_back(*p); + } + } + Bounded_Reference_Cont(const Bounded_Reference_Cont& other) : Base(), _allocator(other._allocator) + { + //std::clog << "copying values container\n"; + for (typename Base::const_iterator it = other.begin(); it != other.end(); ++it) + { + pointer p = _allocator.allocate(1); + new (p.raw()) value_type(*it); + Base::push_back(*p); + } + } + ~Bounded_Reference_Cont() + { + while (not Base::empty()) + { + pointer p = &Base::back(); + p->~value_type(); + _allocator.deallocate(p, 1); + Base::pop_back(); + } + } + +private: + allocator_type _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 + + +namespace boost +{ +namespace intrusive +{ + +template < typename T > +struct pointer_traits< Bounded_Pointer< T > > +{ + typedef T element_type; + typedef Bounded_Pointer< T > pointer; + typedef Bounded_Pointer< const T > const_pointer; + typedef ptrdiff_t difference_type; + typedef Bounded_Reference< T > reference; + + template + struct rebind_pointer + { + typedef typename Bounded_Pointer< T >::template rebind< U >::type type; + }; + + static pointer pointer_to(reference r) { return &r; } + static pointer const_cast_from(const_pointer cptr) { return cptr.unconst(); } +}; + +} // namespace intrusive +} // namespace boost + +template < typename T, typename U > +// typename boost::enable_if< boost::is_same< typename boost::remove_const< T >::type, +// typename boost::remove_const< U >::type >, int >::type = 42 > +bool operator != (const Bounded_Pointer< T >& lhs, const Bounded_Pointer< U >& rhs) +{ + return !(lhs == rhs); +} +template < typename T > +bool operator == (const Bounded_Pointer< T >& lhs, const void* p) +{ + assert(!p); + return lhs == Bounded_Pointer< T >(); +} +template < typename T > +bool operator == (const void* p, const Bounded_Pointer< T >& rhs) +{ + assert(!p); + return Bounded_Pointer< T >() == rhs; +} +template < typename T > +bool operator != (const Bounded_Pointer< T >& lhs, const void* p) +{ + assert(!p); + return lhs != Bounded_Pointer< T >(); +} +template < typename T > +bool operator != (const void* p, const Bounded_Pointer< T >& rhs) +{ + assert(!p); + return Bounded_Pointer< T >() != rhs; +} + + +#endif diff --git a/test/bptr_value.hpp b/test/bptr_value.hpp new file mode 100644 index 0000000..e930cf2 --- /dev/null +++ b/test/bptr_value.hpp @@ -0,0 +1,240 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (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 BOOST_INTRUSIVE_BPTR_VALUE_HPP +#define BOOST_INTRUSIVE_BPTR_VALUE_HPP + +#include +#include +#include "bounded_pointer.hpp" +#include "common_functors.hpp" + + +namespace boost +{ +namespace intrusive +{ + +struct BPtr_Value +{ + static const bool constant_time_size = true; + + BPtr_Value(int value = 42) : value_(value) {} + //BPtr_Value(const BPtr_Value& rhs) = delete; + BPtr_Value(const BPtr_Value& rhs) : value_(rhs.value_) {} + //BPtr_Value(BPtr_Value&&) = delete; + ~BPtr_Value() + { + if (is_linked()) + { + std::cerr << "BPtr_Value dtor: destructing linked value: &=" << (void*)this << "\n"; + assert(false); + } + } + + // testvalue is used in std::vector and thus prev and next + // have to be handled appropriately when copied: + BPtr_Value& operator = (const BPtr_Value& src) + { + if (is_linked()) + { + std::cerr << "BPtr_Value asop: assigning to linked value: &=" << (void*)this << ", src=" << (void*)&src << "\n"; + assert(false); + } + value_ = src.value_; + //_previous = src._previous; + //_next = src._next; + return *this; + } + + // value + int value_; + + // list node hooks + Bounded_Pointer< BPtr_Value > _previous; + Bounded_Pointer< BPtr_Value > _next; + // tree node hooks + Bounded_Pointer< BPtr_Value > _parent; + Bounded_Pointer< BPtr_Value > _l_child; + Bounded_Pointer< BPtr_Value > _r_child; + char _extra; + + bool is_linked() const { return _previous or _next or _parent or _l_child or _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 == 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); } + + friend std::ostream& operator << (std::ostream& os, const BPtr_Value& v) + { + os << v.value_; + return os; + } +}; // class BPtr_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->_previous; } + static void set_previous(node_ptr p, node_ptr prev) { p->_previous = prev; } + static node_ptr get_next(const_node_ptr p) { return p->_next; } + static void set_next(node_ptr p, node_ptr next) { p->_next = next; } +}; + +struct RBTree_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; + typedef char color; + + static node_ptr get_parent(const_node_ptr p) { return p->_parent; } + static void set_parent(node_ptr p, node_ptr parent) { p->_parent = parent; } + static node_ptr get_left(const_node_ptr p) { return p->_l_child; } + static void set_left(node_ptr p, node_ptr l_child) { p->_l_child = l_child; } + static node_ptr get_right(const_node_ptr p) { return p->_r_child; } + static void set_right(node_ptr p, node_ptr r_child) { p->_r_child = r_child; } + static color get_color(const_node_ptr p) { return p->_extra; } + static void set_color(node_ptr p, color c) { p->_extra = c; } + static color black() { return 0; } + static color red() { return 1; } +}; + +struct AVLTree_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; + typedef char balance; + + static node_ptr get_parent(const_node_ptr p) { return p->_parent; } + static void set_parent(node_ptr p, node_ptr parent) { p->_parent = parent; } + static node_ptr get_left(const_node_ptr p) { return p->_l_child; } + static void set_left(node_ptr p, node_ptr l_child) { p->_l_child = l_child; } + static node_ptr get_right(const_node_ptr p) { return p->_r_child; } + static void set_right(node_ptr p, node_ptr r_child) { p->_r_child = r_child; } + static balance get_balance(const_node_ptr p) { return p->_extra; } + static void set_balance(node_ptr p, balance b) { p->_extra = b; } + static balance negative() { return -1; } + static balance zero() { return 0; } + static balance positive() { return 1; } +}; + +template < typename Node_Traits > +struct BPtr_Value_Traits +{ + typedef Node_Traits 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; + + 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 Value_Container; + +template <> +struct Value_Container< 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 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/test/container_size_test.cpp b/test/container_size_test.cpp index d95cee5..00ad27f 100644 --- a/test/container_size_test.cpp +++ b/test/container_size_test.cpp @@ -23,6 +23,7 @@ #include #include #include +#include "itestvalue.hpp" using namespace boost::intrusive; @@ -71,6 +72,16 @@ void test_sizes(boolean, std::size_t wordsize) BOOST_TEST_EQ(sizeof(c), wordsize*2); test_iterator_sizes(c, wordsize); } + { + list< node< list_base_hook<> >, header_holder_type< pointer_holder< list_node > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes(c, wordsize); + } + { + list< node< list_base_hook<> >, constant_time_size, header_holder_type< pointer_holder< list_node > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*1); + test_iterator_sizes(c, wordsize); + } { //slist slist > > > c; BOOST_TEST_EQ(sizeof(c), wordsize*2); @@ -101,6 +112,16 @@ void test_sizes(boolean, std::size_t wordsize) BOOST_TEST_EQ(sizeof(c), wordsize*3); test_iterator_sizes(c, wordsize); } + { + set< node< set_base_hook<> >, header_holder_type< pointer_holder< rbtree_node > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes(c, wordsize); + } + { + set< node< set_base_hook<> >, constant_time_size, header_holder_type< pointer_holder< rbtree_node > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*1); + test_iterator_sizes(c, wordsize); + } { //avl avl_set > > > c; BOOST_TEST_EQ(sizeof(c), wordsize*5); @@ -116,6 +137,16 @@ void test_sizes(boolean, std::size_t wordsize) BOOST_TEST_EQ(sizeof(c), wordsize*3); test_iterator_sizes(c, wordsize); } + { + avl_set< node< avl_set_base_hook<> >, header_holder_type< pointer_holder< avltree_node > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes(c, wordsize); + } + { + avl_set< node< avl_set_base_hook<> >, constant_time_size, header_holder_type< pointer_holder< avltree_node > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*1); + test_iterator_sizes(c, wordsize); + } { //splay splay_set > > > c; BOOST_TEST_EQ(sizeof(c), wordsize*4); diff --git a/test/generic_assoc_test.hpp b/test/generic_assoc_test.hpp index 6dbae8a..5854df0 100644 --- a/test/generic_assoc_test.hpp +++ b/test/generic_assoc_test.hpp @@ -212,27 +212,15 @@ void test_generic_assoc::test_all(value_cont_type test_container_from_iterator(values); } -template < bool Has_Value_Allocator, typename assoc_type, typename value_cont_type > -struct test_clone_impl +template class ContainerDefiner> +void test_generic_assoc + ::test_clone(value_cont_type& values) { -void operator () (value_cont_type& values) -{ - assoc_type testset1 (values.begin(), values.begin() + values.size()); - assoc_type testset2; - - testset2.clone_from(testset1); - BOOST_TEST (testset2 == testset1); - testset2.clear_and_dispose(); - BOOST_TEST (testset2.empty()); -} -}; - -template < typename assoc_type, typename value_cont_type > -struct test_clone_impl< false, assoc_type, value_cont_type > -{ -void operator () (value_cont_type& values) -{ - typedef typename assoc_type::value_type value_type; + typedef typename ContainerDefiner + < value_type + , value_traits + , constant_time_size + >::type assoc_type; assoc_type testset1 (values.begin(), values.begin() + values.size()); assoc_type testset2; @@ -241,21 +229,6 @@ void operator () (value_cont_type& values) testset2.clear_and_dispose(test::delete_disposer()); BOOST_TEST (testset2.empty()); } -}; - -template class ContainerDefiner> -void test_generic_assoc - ::test_clone(value_cont_type& values) -{ - typedef typename ValueTraits::value_type value_type; - typedef typename ContainerDefiner - < value_type - , value_traits - , constant_time_size - >::type assoc_type; - - test_clone_impl< assoc_type::has_value_allocator, assoc_type, value_cont_type >()(values); -} template < bool Has_Container_From_Iterator, typename assoc_type, typename value_cont_type > struct test_container_from_end_impl diff --git a/test/itestvalue.hpp b/test/itestvalue.hpp index 4168501..43ffc5e 100644 --- a/test/itestvalue.hpp +++ b/test/itestvalue.hpp @@ -112,6 +112,12 @@ struct testvalue { return other1.value_ != other2; } }; +template < typename Node_Algorithms, class Hooks, bool ConstantTimeSize > +void swap_nodes(testvalue< Hooks, ConstantTimeSize >& lhs, testvalue< Hooks, ConstantTimeSize >& rhs) +{ + lhs.swap_nodes(rhs); +} + template std::size_t hash_value(const testvalue &t) { @@ -137,25 +143,56 @@ std::ostream& operator<< struct even_odd { - template + template < typename value_type_1, typename value_type_2 > bool operator() - (const testvalue& v1 - ,const testvalue& v2) const + (const value_type_1& v1 + ,const value_type_2& v2) const { - if ((v1.value_ & 1) == (v2.value_ & 1)) - return v1.value_ < v2.value_; + if (((&v1)->value_ & 1) == ((&v2)->value_ & 1)) + return (&v1)->value_ < (&v2)->value_; else - return v2.value_ & 1; + return (&v2)->value_ & 1; } }; struct is_even { - template + template bool operator() - (const testvalue& v1) const - { return (v1.value_ & 1) == 0; } + (const value_type& v1) const + { return ((&v1)->value_ & 1) == 0; } }; + +template +struct Value_Container; + +template < class Hooks, bool ConstantTimeSize > +struct Value_Container< testvalue< Hooks, ConstantTimeSize > > +{ + typedef std::vector< testvalue< Hooks, ConstantTimeSize > > type; +}; + +template < typename T > +class pointer_holder +{ +public: + pointer_holder() : _ptr(new T()) + { + //std::clog << "constructing holder pointing to &=" << (void*)_ptr << "\n"; + } + ~pointer_holder() + { + //std::clog << "destructing holder pointing to &=" << (void*)_ptr << "\n"; + delete _ptr; + } + + const T* get_node() const { return _ptr; } + T* get_node() { return _ptr; } + +private: + T* const _ptr; +}; + /* struct int_testvalue_comp { diff --git a/test/list_test.cpp b/test/list_test.cpp index 7301dcf..06f8eb9 100644 --- a/test/list_test.cpp +++ b/test/list_test.cpp @@ -14,12 +14,15 @@ #include #include #include "itestvalue.hpp" +#include "bptr_value.hpp" #include "smart_ptr.hpp" #include "common_functors.hpp" #include #include #include "test_macros.hpp" #include "test_container.hpp" +#include +#include using namespace boost::intrusive; @@ -39,32 +42,41 @@ struct hooks > nonhook_node_member_type; }; -template + +template < typename List_Type, typename Value_Container > struct test_list { - typedef typename ValueTraits::value_type value_type; - static void test_all(std::vector& values); - static void test_front_back(std::vector& values); - static void test_sort(std::vector& values); - static void test_merge(std::vector& values); - static void test_remove_unique(std::vector& values); - static void test_insert(std::vector& values); - static void test_shift(std::vector& values); - static void test_swap(std::vector& values); - static void test_clone(std::vector& values); - static void test_container_from_end(std::vector& values); + typedef List_Type 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(Value_Container& values); + static void test_front_back(Value_Container& values); + static void test_sort(Value_Container& values); + static void test_merge(Value_Container& values); + static void test_remove_unique(Value_Container& values); + static void test_insert(Value_Container& values); + static void test_shift(Value_Container& values); + static void test_swap(Value_Container& values); + static void test_clone(Value_Container& values); + static void test_container_from_end(Value_Container& values); }; -template -void test_list::test_all(std::vector& values) +template < typename List_Type, typename Value_Container > +void test_list< List_Type, Value_Container >::test_all(Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef list - < value_type - , value_traits - , size_type - , constant_time_size - > list_type; + std::clog << "testing list with:\n" + << " value_type = " << typeid(value_type).name() << "\n" + << " sizeof(value_type) = " << sizeof(value_type) << "\n" + << " link_mode = " << value_traits::link_mode << "\n" + << " node = " << typeid(typename list_type::node).name() << "\n" + << " sizeof(node) = " << sizeof(typename list_type::node) << "\n" + << " node_ptr = " << typeid(typename list_type::node_ptr).name() << "\n" + << " sizeof(node_ptr) = " << sizeof(typename list_type::node_ptr) << "\n" + << " constant_time_size = " << list_type::constant_time_size << "\n" + << " has_container_from_iterator = " << list_type::has_container_from_iterator << "\n" + << " sizeof(list_type) = " << sizeof(list_type) << "\n"; { list_type list(values.begin(), values.end()); test::test_container(list); @@ -85,17 +97,10 @@ void test_list::test_all(std::vector -void test_list - ::test_front_back(std::vector& values) +template < class List_Type, typename Value_Container > +void test_list< List_Type, Value_Container > + ::test_front_back(Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef list - < value_type - , value_traits - , size_type - , constant_time_size - > list_type; list_type testlist; BOOST_TEST (testlist.empty()); @@ -119,19 +124,11 @@ void test_list BOOST_TEST (testlist.empty()); } - //test: constructor, iterator, reverse_iterator, sort, reverse: -template -void test_list - ::test_sort(std::vector& values) +template < class List_Type, typename Value_Container > +void test_list< List_Type, Value_Container > + ::test_sort(Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef list - < value_type - , value_traits - , size_type - , constant_time_size - > list_type; list_type testlist(values.begin(), values.end()); { int init_values [] = { 1, 2, 3, 4, 5 }; @@ -147,17 +144,10 @@ void test_list } //test: merge due to error in merge implementation: -template -void test_list - ::test_remove_unique (std::vector& values) +template < class List_Type, typename Value_Container > +void test_list< List_Type, Value_Container > + ::test_remove_unique (Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef list - < value_type - , value_traits - , size_type - , constant_time_size - > list_type; { list_type list(values.begin(), values.end()); list.remove_if(is_even()); @@ -165,7 +155,7 @@ void test_list TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() ); } { - std::vector values2(values); + Value_Container values2(values); // NOTE: problematic copy of value container list_type list(values.begin(), values.end()); list.insert(list.end(), values2.begin(), values2.end()); list.sort(); @@ -178,17 +168,10 @@ void test_list } //test: merge due to error in merge implementation: -template -void test_list - ::test_merge (std::vector& values) +template < class List_Type, typename Value_Container > +void test_list< List_Type, Value_Container > + ::test_merge (Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef list - < value_type - , value_traits - , size_type - , constant_time_size - > list_type; list_type testlist1, testlist2; testlist1.push_front (values[0]); testlist2.push_front (values[4]); @@ -201,19 +184,12 @@ void test_list } //test: assign, insert, const_iterator, const_reverse_iterator, erase, s_iterator_to: -template -void test_list - ::test_insert(std::vector& values) +template < class List_Type, typename Value_Container > +void test_list< List_Type, Value_Container > + ::test_insert(Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef list - < value_type - , value_traits - , size_type - , constant_time_size - > list_type; list_type testlist; - testlist.assign (&values[0] + 2, &values[0] + 5); + testlist.assign (values.begin() + 2, values.begin() + 5); const list_type& const_testlist = testlist; { int init_values [] = { 3, 4, 5 }; @@ -238,10 +214,10 @@ void test_list BOOST_TEST (&*i == &values[4]); typename list_type::const_iterator ic; - ic = testlist.iterator_to (const_cast(values[4])); + ic = testlist.iterator_to (static_cast< typename list_type::const_reference >(values[4])); BOOST_TEST (&*ic == &values[4]); - ic = list_type::s_iterator_to (const_cast(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); @@ -251,18 +227,10 @@ void test_list TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); } } - -template -void test_list - ::test_shift(std::vector& values) +template < class List_Type, typename Value_Container > +void test_list< List_Type, Value_Container > + ::test_shift(Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef list - < value_type - , value_traits - , size_type - , constant_time_size - > list_type; list_type testlist; const int num_values = (int)values.size(); std::vector expected_values(num_values); @@ -271,7 +239,7 @@ void test_list expected_values.resize(s); //Shift forward all possible positions 3 times for(int i = 0; i < s*3; ++i){ - testlist.insert(testlist.begin(), &values[0], &values[0] + s); + 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); @@ -282,7 +250,7 @@ void test_list //Shift backwards all possible positions for(int i = 0; i < s*3; ++i){ - testlist.insert(testlist.begin(), &values[0], &values[0] + s); + 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); @@ -294,21 +262,14 @@ void test_list } //test: insert (seq-version), swap, splice, erase (seq-version): -template -void test_list - ::test_swap(std::vector& values) +template < class List_Type, typename Value_Container > +void test_list< List_Type, Value_Container > + ::test_swap(Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef list - < value_type - , value_traits - , size_type - , constant_time_size - > list_type; { - list_type testlist1 (&values[0], &values[0] + 2); + list_type testlist1 (values.begin(), values.begin() + 2); list_type testlist2; - testlist2.insert (testlist2.end(), &values[0] + 2, &values[0] + 5); + testlist2.insert (testlist2.end(), values.begin() + 2, values.begin() + 5); testlist1.swap (testlist2); { int init_values [] = { 3, 4, 5 }; @@ -341,72 +302,75 @@ void test_list BOOST_TEST (&testlist1.front() == &values[3]); } { - list_type testlist1 (&values[0], &values[0] + 2); - list_type testlist2 (&values[0] + 3, &values[0] + 5); + list_type testlist1 (values.begin(), values.begin() + 2); + list_type testlist2 (values.begin() + 3, values.begin() + 5); - values[0].swap_nodes(values[2]); + swap_nodes< node_algorithms >(values[0], values[2]); { int init_values [] = { 3, 2 }; TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } - values[2].swap_nodes(values[4]); + 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[0], &values[1]); + list_type testlist1 (values.begin(), values.begin() + 1); { int init_values [] = { 1 }; TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } - values[1].swap_nodes(values[2]); + swap_nodes< node_algorithms >(values[1], values[2]); { int init_values [] = { 1 }; TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } - values[0].swap_nodes(values[2]); + swap_nodes< node_algorithms >(values[0], values[2]); { int init_values [] = { 3 }; TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } - values[0].swap_nodes(values[2]); + swap_nodes< node_algorithms >(values[0], values[2]); { int init_values [] = { 1 }; TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } } - } -template -void test_list - ::test_container_from_end(std::vector& values) +template < class List_Type, typename Value_Container, bool > +struct test_container_from_end_impl { - typedef typename ValueTraits::value_type value_type; - typedef list - < value_type - , value_traits - , size_type - , constant_time_size - > list_type; - list_type testlist1 (&values[0], &values[0] + values.size()); + void operator () (Value_Container&) + { + std::clog << "skipping test_container_from_end\n"; + } +}; + +template < class List_Type, typename Value_Container > +struct test_container_from_end_impl< List_Type, Value_Container, true > +{ + void operator () (Value_Container& values) +{ + typedef List_Type list_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 -void test_list - ::test_clone(std::vector& values) +template < class List_Type, typename Value_Container > +void test_list< List_Type, Value_Container > + ::test_container_from_end(Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef list - < value_type - , value_traits - , size_type - , constant_time_size - > list_type; - list_type testlist1 (&values[0], &values[0] + values.size()); + test_container_from_end_impl< List_Type, Value_Container, List_Type::has_container_from_iterator >()(values); +} + +template < class List_Type, typename Value_Container > +void test_list< List_Type, Value_Container > + ::test_clone(Value_Container& values) +{ + list_type testlist1 (values.begin(), values.begin() + values.size()); list_type testlist2; testlist2.clone_from(testlist1, test::new_cloner(), test::delete_disposer()); @@ -415,42 +379,74 @@ void test_list BOOST_TEST (testlist2.empty()); } -template +template < typename Value_Traits, bool Constant_Time_Size, bool Default_Holder, typename Value_Container > +struct make_and_test_list + : test_list< list< typename Value_Traits::value_type, + value_traits< Value_Traits >, + size_type< std::size_t >, + constant_time_size< Constant_Time_Size > + >, + Value_Container + > +{}; + +template < typename Value_Traits, bool Constant_Time_Size, typename Value_Container > +struct make_and_test_list< Value_Traits, Constant_Time_Size, false, Value_Container > + : test_list< list< typename Value_Traits::value_type, + value_traits< Value_Traits >, + size_type< std::size_t >, + constant_time_size< Constant_Time_Size >, + header_holder_type< pointer_holder< typename Value_Traits::node_traits::node > > + >, + Value_Container + > +{}; + + +template < class VoidPointer, bool ConstantTimeSize, bool Default_Holder > class test_main_template { public: int operator()() { - typedef testvalue, constant_time_size> value_type; + typedef testvalue, ConstantTimeSize> value_type; std::vector data (5); for (int i = 0; i < 5; ++i) data[i].value_ = i + 1; - test_list < typename detail::get_base_value_traits - < value_type - , typename hooks::base_hook_type - >::type - >::test_all(data); - test_list < typename detail::get_member_value_traits - < value_type - , member_hook< value_type - , typename hooks::member_hook_type - , &value_type::node_ - > - >::type - >::test_all(data); - test_list < nonhook_node_member_value_traits< value_type, - typename hooks::nonhook_node_member_type, - &value_type::nhn_member_, - safe_link - > - >::test_all(data); + make_and_test_list < typename detail::get_base_value_traits < + value_type, + typename hooks::base_hook_type + >::type, + ConstantTimeSize, + Default_Holder, + std::vector< value_type > + >::test_all(data); + make_and_test_list < typename detail::get_member_value_traits < + value_type, + member_hook< value_type, typename hooks::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::nonhook_node_member_type, + &value_type::nhn_member_, + safe_link + >, + ConstantTimeSize, + Default_Holder, + std::vector< value_type > + >::test_all(data); + return 0; } }; -template -class test_main_template +template < class VoidPointer, bool Default_Holder > +class test_main_template< VoidPointer, false, Default_Holder > { public: int operator()() @@ -460,40 +456,45 @@ class test_main_template for (int i = 0; i < 5; ++i) data[i].value_ = i + 1; - test_list < typename detail::get_base_value_traits - < value_type - , typename hooks::base_hook_type - >::type - >::test_all(data); - - test_list < typename detail::get_member_value_traits - < value_type - , member_hook< value_type - , typename hooks::member_hook_type - , &value_type::node_ - > - >::type - >::test_all(data); + make_and_test_list < typename detail::get_base_value_traits < + value_type, + typename hooks::base_hook_type + >::type, + false, + Default_Holder, + std::vector< value_type > + >::test_all(data); + make_and_test_list < typename detail::get_member_value_traits < + value_type, + member_hook< value_type, typename hooks::member_hook_type, &value_type::node_> + >::type, + false, + Default_Holder, + std::vector< value_type > + >::test_all(data); // test_list // , safe_link> // >::test_all(data); - test_list < typename detail::get_base_value_traits - < value_type - , typename hooks::auto_base_hook_type - >::type - >::test_all(data); - test_list < typename detail::get_member_value_traits - < value_type - , member_hook< value_type - , typename hooks::auto_member_hook_type - , &value_type::auto_node_ - > - >::type - >::test_all(data); + make_and_test_list < typename detail::get_base_value_traits < + value_type, + typename hooks::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 < + value_type, + member_hook< value_type, typename hooks::auto_member_hook_type, &value_type::auto_node_> + >::type, + false, + Default_Holder, + std::vector< value_type > + >::test_all(data); // test_list } }; +template < bool Constant_Time_Size > +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; + + allocator_type::init(); + 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< Constant_Time_Size >, + header_holder_type< Bounded_Pointer_Holder< value_type > > + >, + Bounded_Reference_Cont< value_type > + >::test_all(ref_cont); + } + + assert(allocator_type::is_clear()); + allocator_type::destroy(); + return 0; + } +}; + int main( int, char* [] ) { - test_main_template()(); - test_main_template, false>()(); - test_main_template()(); - test_main_template, true>()(); + // test combinations of (regular/smart)_ptr x (const/nonconst)_size x (default/non-default)_header_holder + // skip smart_ptr with non-default header_holder + test_main_template()(); + test_main_template, false, true>()(); + test_main_template()(); + test_main_template, true, true>()(); + test_main_template()(); + test_main_template()(); + // test bounded pointers with const/non_const size (always with non-default header_holder) + test_main_template_bptr< true >()(); + test_main_template_bptr< false >()(); + return boost::report_errors(); } diff --git a/test/multiset_test.cpp b/test/multiset_test.cpp index 2a38dcd..b96e206 100644 --- a/test/multiset_test.cpp +++ b/test/multiset_test.cpp @@ -61,8 +61,8 @@ struct hooks }; // container generator with void node allocator -template < bool Void_Allocator > -struct GetContainer_With_Allocator +template < bool Default_Holder > +struct GetContainer_With_Holder { template< class ValueType , class Option1 =void @@ -82,7 +82,7 @@ struct GetContainer // container generator with standard (non-void) node allocator template <> -struct GetContainer_With_Allocator< false > +struct GetContainer_With_Holder< false > { template< class ValueType , class Option1 =void @@ -101,13 +101,13 @@ struct GetContainer , Option1 , Option2 , Option3 - , node_allocator_type< std::allocator< node > > + , header_holder_type< pointer_holder< node > > > type; }; }; -template +template class test_main_template { public: @@ -120,7 +120,7 @@ class test_main_template < value_type , typename hooks::base_hook_type >::type - , GetContainer_With_Allocator< Void_Allocator >::template GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_multiset < typename detail::get_member_value_traits < value_type @@ -129,21 +129,21 @@ class test_main_template , &value_type::node_ > >::type - , GetContainer_With_Allocator< Void_Allocator >::template GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_multiset < nonhook_node_member_value_traits< value_type, typename hooks::nonhook_node_member_type, &value_type::nhn_member_, safe_link >, - GetContainer_With_Allocator< Void_Allocator >::template GetContainer + GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); return 0; } }; -template -class test_main_template +template +class test_main_template { public: int operator()() @@ -155,7 +155,7 @@ class test_main_template < value_type , typename hooks::base_hook_type >::type - , GetContainer_With_Allocator< Void_Allocator >::template GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_multiset < typename detail::get_member_value_traits @@ -165,14 +165,14 @@ class test_main_template , &value_type::node_ > >::type - , GetContainer_With_Allocator< Void_Allocator >::template GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_multiset < typename detail::get_base_value_traits < value_type , typename hooks::auto_base_hook_type >::type - , GetContainer_With_Allocator< Void_Allocator >::template GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_multiset < typename detail::get_member_value_traits @@ -182,14 +182,14 @@ class test_main_template , &value_type::auto_node_ > >::type - , GetContainer_With_Allocator< Void_Allocator >::template GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); return 0; } }; // container generator which ignores further parametrization, except for compare option -template < typename Value_Traits, bool Constant_Time_Size, typename Allocator > +template < typename Value_Traits, bool Constant_Time_Size, typename Header_Holder > struct Get_Preset_Container { template < class @@ -208,7 +208,7 @@ struct Get_Preset_Container value_traits< Value_Traits >, constant_time_size< Constant_Time_Size >, compare< compare_option >, - node_allocator_type< Allocator > + header_holder_type< Header_Holder > > type; }; }; @@ -224,7 +224,8 @@ struct test_main_template_bptr allocator_type::init(); test::test_generic_multiset< value_traits, - Get_Preset_Container< value_traits, Constant_Time_Size, allocator_type >::template GetContainer + Get_Preset_Container< value_traits, Constant_Time_Size, + Bounded_Pointer_Holder< value_type > >::template GetContainer >::test_all(); assert(allocator_type::is_clear()); allocator_type::destroy(); diff --git a/test/set_test.cpp b/test/set_test.cpp index 8a2c3c6..537335c 100644 --- a/test/set_test.cpp +++ b/test/set_test.cpp @@ -62,8 +62,8 @@ struct hooks }; // container generator with void node allocator -template < bool Void_Allocator > -struct GetContainer_With_Allocator +template < bool Default_Holder > +struct GetContainer_With_Holder { template< class ValueType , class Option1 =void @@ -83,7 +83,7 @@ struct GetContainer // container generator with standard (non-void) node allocator template <> -struct GetContainer_With_Allocator< false > +struct GetContainer_With_Holder< false > { template< class ValueType , class Option1 =void @@ -102,13 +102,13 @@ struct GetContainer , Option1 , Option2 , Option3 - , node_allocator_type< std::allocator< node > > + , header_holder_type< pointer_holder< node > > > type; }; }; -template +template class test_main_template { public: @@ -121,7 +121,7 @@ class test_main_template < value_type , typename hooks::base_hook_type >::type - , GetContainer_With_Allocator< Void_Allocator >::template GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_set < typename detail::get_member_value_traits < value_type @@ -130,21 +130,21 @@ class test_main_template , &value_type::node_ > >::type - , GetContainer_With_Allocator< Void_Allocator >::template GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_set < nonhook_node_member_value_traits< value_type, typename hooks::nonhook_node_member_type, &value_type::nhn_member_, safe_link >, - GetContainer_With_Allocator< Void_Allocator >::template GetContainer + GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); return 0; } }; -template -class test_main_template +template +class test_main_template { public: int operator()() @@ -156,7 +156,7 @@ class test_main_template < value_type , typename hooks::base_hook_type >::type - , GetContainer_With_Allocator< Void_Allocator >::template GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_set < typename detail::get_member_value_traits @@ -166,14 +166,14 @@ class test_main_template , &value_type::node_ > >::type - , GetContainer_With_Allocator< Void_Allocator >::template GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_set < typename detail::get_base_value_traits < value_type , typename hooks::auto_base_hook_type >::type - , GetContainer_With_Allocator< Void_Allocator >::template GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); test::test_generic_set < typename detail::get_member_value_traits @@ -183,7 +183,7 @@ class test_main_template , &value_type::auto_node_ > >::type - , GetContainer_With_Allocator< Void_Allocator >::template GetContainer + , GetContainer_With_Holder< Default_Holder >::template GetContainer >::test_all(); return 0; @@ -191,7 +191,7 @@ class test_main_template }; // container generator which ignores further parametrization, except for compare option -template < typename Value_Traits, bool Constant_Time_Size, typename Allocator > +template < typename Value_Traits, bool Constant_Time_Size, typename Header_Holder > struct Get_Preset_Container { template < class @@ -210,7 +210,7 @@ struct Get_Preset_Container value_traits< Value_Traits >, constant_time_size< Constant_Time_Size >, compare< compare_option >, - node_allocator_type< Allocator > + header_holder_type< Header_Holder > > type; }; }; @@ -226,7 +226,9 @@ struct test_main_template_bptr allocator_type::init(); test::test_generic_set< value_traits, - Get_Preset_Container< value_traits, Constant_Time_Size, allocator_type >::template GetContainer + Get_Preset_Container< value_traits, Constant_Time_Size, + Bounded_Pointer_Holder< value_type > + >::template GetContainer >::test_all(); assert(allocator_type::is_clear()); allocator_type::destroy(); diff --git a/test/slist_test.cpp b/test/slist_test.cpp index cde9a31..e6c544d 100644 --- a/test/slist_test.cpp +++ b/test/slist_test.cpp @@ -15,12 +15,14 @@ #include #include #include "itestvalue.hpp" +#include "bptr_value.hpp" #include "smart_ptr.hpp" #include "common_functors.hpp" #include #include #include "test_macros.hpp" #include "test_container.hpp" +#include using namespace boost::intrusive; @@ -40,39 +42,47 @@ struct hooks > nonhook_node_member_type; }; -template +template < typename List_Type, typename Value_Container > struct test_slist { - typedef typename ValueTraits::value_type value_type; - static void test_all(std::vector& values); - static void test_front(std::vector& values); - static void test_back(std::vector& values, detail::bool_); - static void test_back(std::vector& values, detail::bool_); - static void test_sort(std::vector& values); - static void test_merge(std::vector& values); - static void test_remove_unique(std::vector& values); - static void test_insert(std::vector& values); - static void test_shift(std::vector& values); - static void test_swap(std::vector& values); - static void test_slow_insert(std::vector& values); - static void test_clone(std::vector& values); - static void test_container_from_end(std::vector &, detail::bool_){} - static void test_container_from_end(std::vector &values, detail::bool_); + typedef List_Type 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(Value_Container& values); + static void test_front(Value_Container& values); + static void test_back(Value_Container& values, detail::bool_); + static void test_back(Value_Container& values, detail::bool_); + static void test_sort(Value_Container& values); + static void test_merge(Value_Container& values); + static void test_remove_unique(Value_Container& values); + static void test_insert(Value_Container& values); + static void test_shift(Value_Container& values); + static void test_swap(Value_Container& values); + static void test_slow_insert(Value_Container& values); + static void test_clone(Value_Container& values); + static void test_container_from_end(Value_Container &, detail::bool_){} + static void test_container_from_end(Value_Container &values, detail::bool_); }; -template -void test_slist - ::test_all (std::vector& values) +template < typename List_Type, typename Value_Container > +void test_slist< List_Type, Value_Container > + ::test_all (Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef slist - < value_type - , value_traits - , size_type - , constant_time_size - , linear - , cache_last - > list_type; + std::clog << "testing slist with:\n" + << " value_type = " << typeid(value_type).name() << "\n" + << " sizeof(value_type) = " << sizeof(value_type) << "\n" + << " link_mode = " << value_traits::link_mode << "\n" + << " node = " << typeid(typename list_type::node).name() << "\n" + << " sizeof(node) = " << sizeof(typename list_type::node) << "\n" + << " node_ptr = " << typeid(typename list_type::node_ptr).name() << "\n" + << " sizeof(node_ptr) = " << sizeof(typename list_type::node_ptr) << "\n" + << " constant_time_size = " << list_type::constant_time_size << "\n" + << " linear = " << list_type::linear << "\n" + << " cache_last = " << list_type::cache_last << "\n" + << " has_container_from_iterator = " << list_type::has_container_from_iterator << "\n" + << " sizeof(list_type) = " << sizeof(list_type) << "\n"; { list_type list(values.begin(), values.end()); test::test_container(list); @@ -81,7 +91,7 @@ void test_slist test::test_sequence_container(list, values); } test_front(values); - test_back(values, detail::bool_()); + test_back(values, detail::bool_()); test_sort(values); test_merge (values); test_remove_unique(values); @@ -90,23 +100,14 @@ void test_slist test_slow_insert (values); test_swap(values); test_clone(values); - test_container_from_end(values, detail::bool_()); + test_container_from_end(values, detail::bool_()); } //test: push_front, pop_front, front, size, empty: -template -void test_slist - ::test_front(std::vector& values) +template < typename List_Type, typename Value_Container > +void test_slist< List_Type, Value_Container > + ::test_front(Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef slist - < value_type - , value_traits - , size_type - , constant_time_size - , linear - , cache_last - > list_type; list_type testlist; BOOST_TEST (testlist.empty()); @@ -127,19 +128,10 @@ void test_slist } //test: push_front, pop_front, front, size, empty: -template -void test_slist - ::test_back(std::vector& values, detail::bool_) +template < typename List_Type, typename Value_Container > +void test_slist< List_Type, Value_Container > + ::test_back(Value_Container& values, detail::bool_) { - typedef typename ValueTraits::value_type value_type; - typedef slist - < value_type - , value_traits - , size_type - , constant_time_size - , linear - , cache_last - > list_type; list_type testlist; BOOST_TEST (testlist.empty()); @@ -154,26 +146,17 @@ void test_slist } //test: push_front, pop_front, front, size, empty: -template -void test_slist - ::test_back(std::vector&, detail::bool_) +template < typename List_Type, typename Value_Container > +void test_slist< List_Type, Value_Container > + ::test_back(Value_Container&, detail::bool_) {} //test: merge due to error in merge implementation: -template -void test_slist - ::test_merge (std::vector& values) +template < typename List_Type, typename Value_Container > +void test_slist< List_Type, Value_Container > + ::test_merge (Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef slist - < value_type - , value_traits - , size_type - , constant_time_size - , linear - , cache_last - > list_type; list_type testlist1, testlist2; testlist1.push_front (values[0]); testlist2.push_front (values[4]); @@ -186,19 +169,10 @@ void test_slist } //test: merge due to error in merge implementation: -template -void test_slist - ::test_remove_unique (std::vector& values) +template < typename List_Type, typename Value_Container > +void test_slist< List_Type, Value_Container > + ::test_remove_unique (Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef slist - < value_type - , value_traits - , size_type - , constant_time_size - , linear - , cache_last - > list_type; { list_type list(values.begin(), values.end()); list.remove_if(is_even()); @@ -206,7 +180,7 @@ void test_slist TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() ); } { - std::vector values2(values); + Value_Container values2(values); list_type list(values.begin(), values.end()); list.insert_after(list.before_begin(), values2.begin(), values2.end()); list.sort(); @@ -219,19 +193,10 @@ void test_slist } //test: constructor, iterator, sort, reverse: -template -void test_slist - ::test_sort(std::vector& values) +template < typename List_Type, typename Value_Container > +void test_slist< List_Type, Value_Container > + ::test_sort(Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef slist - < value_type - , value_traits - , size_type - , constant_time_size - , linear - , cache_last - > list_type; list_type testlist (values.begin(), values.end()); { int init_values [] = { 1, 2, 3, 4, 5 }; @@ -247,21 +212,12 @@ void test_slist } //test: assign, insert_after, const_iterator, erase_after, s_iterator_to, previous: -template -void test_slist - ::test_insert(std::vector& values) +template < typename List_Type, typename Value_Container > +void test_slist< List_Type, Value_Container > + ::test_insert(Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef slist - < value_type - , value_traits - , size_type - , constant_time_size - , linear - , cache_last - > list_type; list_type testlist; - testlist.assign (&values[0] + 2, &values[0] + 5); + testlist.assign (values.begin() + 2, values.begin() + 5); const list_type& const_testlist = testlist; { int init_values [] = { 3, 4, 5 }; @@ -280,9 +236,9 @@ void test_slist BOOST_TEST (&*i == &values[4]); typename list_type::const_iterator ic; - ic = testlist.iterator_to (const_cast(values[4])); + ic = testlist.iterator_to (static_cast< typename list_type::const_reference >(values[4])); BOOST_TEST (&*ic == &values[4]); - ic = list_type::s_iterator_to (const_cast(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); @@ -295,22 +251,13 @@ void test_slist } //test: insert, const_iterator, erase, siterator_to: -template -void test_slist - ::test_slow_insert (std::vector& values) +template < typename List_Type, typename Value_Container > +void test_slist< List_Type, Value_Container > + ::test_slow_insert (Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef slist - < value_type - , value_traits - , size_type - , constant_time_size - , linear - , cache_last - > list_type; list_type testlist; testlist.push_front (values[4]); - testlist.insert (testlist.begin(), &values[0] + 2, &values[0] + 4); + testlist.insert (testlist.begin(), values.begin() + 2, values.begin() + 4); const list_type& const_testlist = testlist; { int init_values [] = { 3, 4, 5 }; @@ -337,24 +284,14 @@ void test_slist testlist.erase (++testlist.begin(), testlist.end()); BOOST_TEST (testlist.size() == 1); - BOOST_TEST (testlist.front().value_ == 3); + BOOST_TEST (testlist.begin()->value_ == 3); } -template -void test_slist - ::test_shift(std::vector& values) +template < typename List_Type, typename Value_Container > +void test_slist< List_Type, Value_Container > + ::test_shift(Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef slist - < value_type - , value_traits - , size_type - , constant_time_size - , linear - , cache_last - > list_type; list_type testlist; - const int num_values = (int)values.size(); std::vector expected_values(num_values); @@ -362,7 +299,7 @@ void test_slist 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[0], &values[0] + s); + 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); @@ -374,7 +311,7 @@ void test_slist //Shift backwards all possible positions for(int i = 0; i < s*3; ++i){ - testlist.insert_after(testlist.before_begin(), &values[0], &values[0] + s); + 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); @@ -387,23 +324,14 @@ void test_slist } //test: insert_after (seq-version), swap, splice_after: -template -void test_slist - ::test_swap(std::vector& values) +template < typename List_Type, typename Value_Container > +void test_slist< List_Type, Value_Container > + ::test_swap(Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef slist - < value_type - , value_traits - , size_type - , constant_time_size - , linear - , cache_last - > list_type; { - list_type testlist1 (&values[0], &values[0] + 2); + list_type testlist1 (values.begin(), values.begin() + 2); list_type testlist2; - testlist2.insert_after (testlist2.before_begin(), &values[0] + 2, &values[0] + 5); + 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() ); } @@ -428,7 +356,7 @@ void test_slist TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } } { //Now test swap when testlist2 is empty - list_type testlist1 (&values[0], &values[0] + 2); + list_type testlist1 (values.begin(), values.begin() + 2); list_type testlist2; testlist1.swap(testlist2); BOOST_TEST (testlist1.empty()); @@ -436,7 +364,7 @@ void test_slist TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } } { //Now test swap when testlist1 is empty - list_type testlist2 (&values[0], &values[0] + 2); + list_type testlist2 (values.begin(), values.begin() + 2); list_type testlist1; testlist1.swap(testlist2); BOOST_TEST (testlist2.empty()); @@ -451,14 +379,14 @@ void test_slist if(!list_type::linear) { - list_type testlist1 (&values[0], &values[0] + 2); - list_type testlist2 (&values[0] + 3, &values[0] + 5); + list_type testlist1 (values.begin(), values.begin() + 2); + list_type testlist2 (values.begin() + 3, values.begin() + 5); - values[0].swap_nodes(values[2]); + swap_nodes< node_algorithms >(values[0], values[2]); { int init_values [] = { 3, 2 }; TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } - values[2].swap_nodes(values[4]); + 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 }; @@ -466,52 +394,42 @@ void test_slist } if(!list_type::linear) { - list_type testlist1 (&values[0], &values[0]+1); + list_type testlist1 (values.begin(), values.begin()+1); if(testlist1.size() != 1){ abort(); } { int init_values [] = { 1 }; TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } - values[1].swap_nodes(values[2]); + 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()); + BOOST_TEST(!(&values[1])->is_linked()); + BOOST_TEST(!(&values[2])->is_linked()); { int init_values [] = { 1 }; TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } - values[0].swap_nodes(values[2]); + 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()); + BOOST_TEST((&values[2])->is_linked()); + BOOST_TEST(!(&values[0])->is_linked()); { int init_values [] = { 3 }; TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } - values[0].swap_nodes(values[2]); + 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()); + BOOST_TEST(!(&values[2])->is_linked()); + BOOST_TEST((&values[0])->is_linked()); { int init_values [] = { 1 }; TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } } } -template -void test_slist - ::test_clone(std::vector& values) +template < typename List_Type, typename Value_Container > +void test_slist< List_Type, Value_Container > + ::test_clone(Value_Container& values) { - typedef typename ValueTraits::value_type value_type; - typedef slist - < value_type - , value_traits - , size_type - , constant_time_size - , linear - , cache_last - > list_type; - - list_type testlist1 (&values[0], &values[0] + values.size()); + list_type testlist1 (values.begin(), values.begin() + values.size()); list_type testlist2; testlist2.clone_from(testlist1, test::new_cloner(), test::delete_disposer()); @@ -520,144 +438,193 @@ void test_slist BOOST_TEST (testlist2.empty()); } -template -void test_slist - ::test_container_from_end(std::vector& values +template < typename List_Type, typename Value_Container > +void test_slist< List_Type, Value_Container > + ::test_container_from_end(Value_Container& values ,detail::bool_) { - typedef typename ValueTraits::value_type value_type; - typedef slist - < value_type - , value_traits - , size_type - , constant_time_size - , linear - , cache_last - > list_type; - list_type testlist1 (&values[0], &values[0] + values.size()); + + 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 +template < typename Value_Traits, bool Constant_Time_Size, bool Linear, bool CacheLast, bool Default_Holder, typename Value_Container > +struct make_and_test_slist + : test_slist< slist< typename Value_Traits::value_type, + value_traits< Value_Traits >, + size_type< std::size_t >, + constant_time_size< Constant_Time_Size >, + linear, + cache_last + >, + Value_Container + > +{}; + +template < typename Value_Traits, bool Constant_Time_Size, bool Linear, bool CacheLast, typename Value_Container > +struct make_and_test_slist< Value_Traits, Constant_Time_Size, Linear, CacheLast, false, Value_Container > + : test_slist< slist< typename Value_Traits::value_type, + value_traits< Value_Traits >, + size_type< std::size_t >, + constant_time_size< Constant_Time_Size >, + linear, + cache_last, + header_holder_type< pointer_holder< typename Value_Traits::node_traits::node > > + >, + Value_Container + > +{}; + +template class test_main_template { public: int operator()() { typedef testvalue , constant_time_size> value_type; - std::vector data (5); + std::vector< value_type > data (5); for (int i = 0; i < 5; ++i) data[i].value_ = i + 1; - test_slist < typename detail::get_base_value_traits + make_and_test_slist < typename detail::get_base_value_traits < value_type , typename hooks::base_hook_type >::type + , constant_time_size , false , false + , Default_Holder + , std::vector< value_type > >::test_all(data); - test_slist < typename detail::get_member_value_traits + make_and_test_slist < typename detail::get_member_value_traits < value_type , member_hook< value_type , typename hooks::member_hook_type , &value_type::node_ > >::type + , constant_time_size , false , false + , Default_Holder + , std::vector< value_type > >::test_all(data); - test_slist < nonhook_node_member_value_traits< value_type, + make_and_test_slist < nonhook_node_member_value_traits< value_type, typename hooks::nonhook_node_member_type, &value_type::nhn_member_, safe_link - >, - false, - false + > + , constant_time_size + , false + , false + , Default_Holder + , std::vector< value_type > >::test_all(data); //Now linear slists - test_slist < typename detail::get_base_value_traits + make_and_test_slist < typename detail::get_base_value_traits < value_type , typename hooks::base_hook_type >::type + , constant_time_size , true , false + , Default_Holder + , std::vector< value_type > >::test_all(data); - test_slist < typename detail::get_member_value_traits + make_and_test_slist < typename detail::get_member_value_traits < value_type , member_hook< value_type , typename hooks::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 - test_slist < typename detail::get_base_value_traits + make_and_test_slist < typename detail::get_base_value_traits < value_type , typename hooks::base_hook_type >::type + , constant_time_size , false , true + , Default_Holder + , std::vector< value_type > >::test_all(data); - test_slist < typename detail::get_member_value_traits + make_and_test_slist < typename detail::get_member_value_traits < value_type , member_hook< value_type , typename hooks::member_hook_type , &value_type::node_ > >::type + , constant_time_size , false , true + , Default_Holder + , std::vector< value_type > >::test_all(data); //Now linear slists - test_slist < typename detail::get_base_value_traits + make_and_test_slist < typename detail::get_base_value_traits < value_type , typename hooks::base_hook_type >::type + , constant_time_size , true , true + , Default_Holder + , std::vector< value_type > >::test_all(data); - test_slist < typename detail::get_member_value_traits + make_and_test_slist < typename detail::get_member_value_traits < value_type , member_hook< value_type , typename hooks::member_hook_type , &value_type::node_ > >::type + , constant_time_size , true , true + , Default_Holder + , std::vector< value_type > >::test_all(data); return 0; } }; -template -class test_main_template +template +class test_main_template { public: int operator()() { typedef testvalue , false> value_type; - std::vector data (5); + std::vector< value_type > data (5); for (int i = 0; i < 5; ++i) data[i].value_ = i + 1; - test_slist < typename detail::get_base_value_traits + make_and_test_slist < typename detail::get_base_value_traits < value_type , typename hooks::base_hook_type >::type , false , false + , false + , Default_Holder + , std::vector< value_type > >::test_all(data); - test_slist < typename detail::get_member_value_traits + make_and_test_slist < typename detail::get_member_value_traits < value_type , member_hook< value_type , typename hooks::member_hook_type @@ -666,17 +633,23 @@ class test_main_template >::type , false , false + , false + , Default_Holder + , std::vector< value_type > >::test_all(data); - test_slist < typename detail::get_base_value_traits + make_and_test_slist < typename detail::get_base_value_traits < value_type , typename hooks::auto_base_hook_type >::type , false , false + , false + , Default_Holder + , std::vector< value_type > >::test_all(data); - test_slist < typename detail::get_member_value_traits + make_and_test_slist < typename detail::get_member_value_traits < value_type , member_hook< value_type , typename hooks::auto_member_hook_type @@ -685,37 +658,74 @@ class test_main_template >::type , false , false + , false + , Default_Holder + , std::vector< value_type > >::test_all(data); - test_slist < typename detail::get_base_value_traits + make_and_test_slist < typename detail::get_base_value_traits < value_type , typename hooks::base_hook_type >::type + , false , true , false + , Default_Holder + , std::vector< value_type > >::test_all(data); - test_slist < typename detail::get_member_value_traits + make_and_test_slist < typename detail::get_member_value_traits < value_type , member_hook< value_type , typename hooks::member_hook_type , &value_type::node_ > >::type + , false , true , false + , Default_Holder + , std::vector< value_type > >::test_all(data); //Now cache last - test_slist < typename detail::get_base_value_traits + make_and_test_slist < typename detail::get_base_value_traits + < value_type + , typename hooks::base_hook_type + >::type + , false + , false + , true + , Default_Holder + , std::vector< value_type > + >::test_all(data); + + make_and_test_slist < typename detail::get_member_value_traits + < value_type + , member_hook< value_type + , typename hooks::member_hook_type + , &value_type::node_ + > + >::type + , false + , false + , true + , Default_Holder + , std::vector< value_type > + >::test_all(data); + + make_and_test_slist < typename detail::get_base_value_traits < value_type , typename hooks::base_hook_type >::type , false , true + , true + , Default_Holder + , std::vector< value_type > >::test_all(data); - test_slist < typename detail::get_member_value_traits + make_and_test_slist < typename detail::get_member_value_traits < value_type , member_hook< value_type , typename hooks::member_hook_type @@ -724,36 +734,66 @@ class test_main_template >::type , false , true + , true + , Default_Holder + , std::vector< value_type > >::test_all(data); + return 0; + } +}; - test_slist < typename detail::get_base_value_traits - < value_type - , typename hooks::base_hook_type - >::type - , true - , true - >::test_all(data); +template < bool Constant_Time_Size > +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; - test_slist < typename detail::get_member_value_traits - < value_type - , member_hook< value_type - , typename hooks::member_hook_type - , &value_type::node_ - > - >::type - , true - , true - >::test_all(data); + allocator_type::init(); + 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< Constant_Time_Size >, + header_holder_type< Bounded_Pointer_Holder< value_type > > + >, + Bounded_Reference_Cont< value_type > + >::test_all(ref_cont); + } + + assert(allocator_type::is_clear()); + allocator_type::destroy(); return 0; } }; int main(int, char* []) { - test_main_template()(); - test_main_template, false>()(); - test_main_template()(); - test_main_template, true>()(); + // test combinations of (regular/smart)_ptr x (const/nonconst)_size x (default/non-default)_header_holder + // skip smart_ptr with non-default header_holder + test_main_template()(); + test_main_template, false, true>()(); + test_main_template()(); + test_main_template, true, true>()(); + test_main_template()(); + test_main_template()(); + // test bounded pointers with const/non_const size (always with non-default header_holder) + test_main_template_bptr< true >()(); + test_main_template_bptr< false >()(); + return boost::report_errors(); } #include