- Implemented map and multimap-like interfaces.

-  Refactored hashtable containers to reduce template instantiations.
This commit is contained in:
Ion Gaztañaga
2015-06-04 11:16:21 +02:00
parent 9ddcfa8e7d
commit 51de75799b
57 changed files with 5962 additions and 8937 deletions
+90 -208
View File
@@ -1,7 +1,7 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2013.
// (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
@@ -11,237 +11,119 @@
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/avl_set.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "avl_test_common.hpp"
#include "generic_multiset_test.hpp"
namespace boost { namespace intrusive { namespace test {
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct has_insert_before<boost::intrusive::avl_multiset<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = true;
};
}}}
using namespace boost::intrusive;
struct my_tag;
template<class VoidPointer>
struct hooks
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef avl_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
typedef avl_set_base_hook
<link_mode<auto_unlink>
, void_pointer<VoidPointer>
, tag<my_tag>
, optimize_size<true> > auto_base_hook_type;
typedef avl_set_member_hook
<void_pointer<VoidPointer> > 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, false >,
avltree_algorithms
> nonhook_node_member_type;
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
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));
};
};
// container generator with void node allocator
template < bool Default_Holder >
struct GetContainer_With_Holder
{
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainer
{
typedef boost::intrusive::avl_multiset
< ValueType
, Option1
, Option2
, Option3
> type;
};
};
// 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 VoidPointer, bool constant_time_size, bool Default_Holder>
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template
{
public:
int operator()()
static void execute()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , constant_time_size> value_type;
test::test_generic_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < nonhook_node_member_value_traits< value_type,
typename hooks<VoidPointer>::nonhook_node_member_type,
&value_type::nhn_member_,
safe_link
>,
GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
return 0;
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
< base_hook_t
, rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
//member
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::member_value_traits
, typename testval_traits_t::auto_member_value_traits
>::type member_hook_t;
test::test_generic_multiset
< member_hook_t
, rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
//nonmember
test::test_generic_multiset
< typename testval_traits_t::nonhook_value_traits
, rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool Default_Holder>
class test_main_template<VoidPointer, false, Default_Holder>
{
public:
int operator()()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , false> value_type;
test::test_generic_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::auto_base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::auto_member_hook_type
, &value_type::auto_node_
>
>::type
, 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 ConstantTimeSize, typename HeaderHolder >
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< ConstantTimeSize >,
compare< compare_option >,
header_holder_type< HeaderHolder >
> type;
};
};
template < bool ConstantTimeSize >
template < bool ConstantTimeSize, bool Map >
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;
static void execute()
{
typedef BPtr_Value_Traits< AVLTree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
allocator_type::init();
test::test_generic_multiset< value_traits,
Get_Preset_Container< value_traits, ConstantTimeSize,
bounded_pointer_holder< value_type > >::template GetContainer
>::test_all();
assert(allocator_type::is_clear());
allocator_type::destroy();
}
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_multiset
< value_traits
, rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
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 (plain pointers) x (nonconst/const size) x (standard node allocator)
test_main_template<void*, false, false>()();
test_main_template<void*, true, false>()();
// test (bounded pointers) x (nonconst/const size) x (special node allocator)
//AVL with bptr failing in some platforms, to investigate.
//test_main_template_bptr< true >()();
//test_main_template_bptr< false >()();
//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>::execute();
test_main_template<void*, false, false, true>::execute();
//test_main_template<void*, false, true, false>::execute();
test_main_template<void*, false, true, true>::execute();
//test_main_template<void*, true, false, false>::execute();
test_main_template<void*, true, false, true>::execute();
//test_main_template<void*, true, true, false>::execute();
test_main_template<void*, true, true, true>::execute();
//smart_ptr
test_main_template<smart_ptr<void>, false, false, false>::execute();
//test_main_template<smart_ptr<void>, false, false, true>::execute();
test_main_template<smart_ptr<void>, false, true, false>::execute();
//test_main_template<smart_ptr<void>, false, true, true>::execute();
test_main_template<smart_ptr<void>, true, false, false>::execute();
//test_main_template<smart_ptr<void>, true, false, true>::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();
}
+90 -209
View File
@@ -1,7 +1,7 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2013.
// (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
@@ -14,235 +14,116 @@
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "avl_test_common.hpp"
#include "generic_set_test.hpp"
namespace boost { namespace intrusive { namespace test {
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct has_insert_before<boost::intrusive::avl_set<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = true;
};
}}}
using namespace boost::intrusive;
struct my_tag;
template<class VoidPointer>
struct hooks
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef avl_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
typedef avl_set_base_hook
<link_mode<auto_unlink>
, void_pointer<VoidPointer>
, tag<my_tag>
, optimize_size<true> > auto_base_hook_type;
typedef avl_set_member_hook
<void_pointer<VoidPointer> > 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, false >,
avltree_algorithms
> nonhook_node_member_type;
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
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));
};
};
// container generator with void node allocator
template < bool Default_Holder >
struct GetContainer_With_Holder
{
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainer
{
typedef boost::intrusive::avl_set
< ValueType
, Option1
, Option2
, Option3
> type;
};
};
// 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 VoidPointer, bool constant_time_size, bool Default_Holder>
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template
{
public:
int operator()()
static void execute()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , constant_time_size> value_type;
test::test_generic_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < nonhook_node_member_value_traits< value_type,
typename hooks<VoidPointer>::nonhook_node_member_type,
&value_type::nhn_member_,
safe_link
>,
GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
return 0;
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
< base_hook_t
, rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
//member
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::member_value_traits
, typename testval_traits_t::auto_member_value_traits
>::type member_hook_t;
test::test_generic_set
< member_hook_t
, rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
//nonmember
test::test_generic_set
< typename testval_traits_t::nonhook_value_traits
, rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool Default_Holder>
class test_main_template<VoidPointer, false, Default_Holder>
{
public:
int operator()()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , false> value_type;
test::test_generic_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::auto_base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::auto_member_hook_type
, &value_type::auto_node_
>
>::type
, 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 ConstantTimeSize, typename HeaderHolder >
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< ConstantTimeSize >,
compare< compare_option >,
header_holder_type< HeaderHolder >
> type;
};
};
template < bool ConstantTimeSize >
template < bool ConstantTimeSize, bool Map >
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;
static void execute()
{
typedef BPtr_Value_Traits< AVLTree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
allocator_type::init();
test::test_generic_set< value_traits,
Get_Preset_Container< value_traits, ConstantTimeSize,
bounded_pointer_holder< value_type > >::template GetContainer
>::test_all();
assert(allocator_type::is_clear());
allocator_type::destroy();
}
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_set
< value_traits
, rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
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 (plain pointers) x (nonconst/const size) x (standard node allocator)
test_main_template<void*, false, false>()();
test_main_template<void*, true, false>()();
// test (bounded pointers) x (nonconst/const size) x (special node allocator)
//AVL with bptr failing in some platforms, to investigate.
//test_main_template_bptr< true >()();
//test_main_template_bptr< false >()();
//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>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false>::execute();
//test_main_template<void*, true, true, true>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true>::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();
}
+31 -1
View File
@@ -218,6 +218,7 @@ class bounded_allocator
assert(i < max_offset);
p.m_offset = i;
m_in_use[p.m_offset] = true;
++m_in_use_count;
return p;
}
@@ -227,6 +228,7 @@ class bounded_allocator
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
@@ -268,14 +270,31 @@ class bounded_allocator
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
@@ -306,7 +325,7 @@ class bounded_reference_cont
using Base::operator[];
using Base::push_back;
bounded_reference_cont(size_t n = 0)
explicit bounded_reference_cont(size_t n = 0)
: Base(), m_allocator()
{
for (size_t i = 0; i < n; ++i){
@@ -338,6 +357,17 @@ class bounded_reference_cont
}
}
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(); }
+52 -45
View File
@@ -26,7 +26,7 @@ struct BPtr_Value
{
static const bool constant_time_size = true;
BPtr_Value(int value = 42)
explicit BPtr_Value(int value = 42)
: value_(value)
{}
@@ -55,7 +55,7 @@ struct BPtr_Value
}
// value
int value_;
int_holder value_;
// list node hooks
bounded_pointer< BPtr_Value > m_previous;
@@ -66,6 +66,12 @@ struct BPtr_Value
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; }
@@ -119,47 +125,6 @@ struct List_BPtr_Node_Traits
static void set_next(node_ptr p, node_ptr next) { p->m_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 signed char color;
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; }
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
{
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 signed char balance;
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; }
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; }
};
struct Tree_BPtr_Node_Traits
{
typedef BPtr_Value val_t;
@@ -175,6 +140,31 @@ struct Tree_BPtr_Node_Traits
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
{
@@ -197,10 +187,10 @@ struct BPtr_Value_Traits
};
template < typename >
struct Value_Container;
struct ValueContainer;
template <>
struct Value_Container< BPtr_Value >
struct ValueContainer< BPtr_Value >
{
typedef bounded_reference_cont< BPtr_Value > type;
};
@@ -224,6 +214,23 @@ class new_cloner< BPtr_Value >
}
};
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 >
{
+8
View File
@@ -42,6 +42,14 @@ class new_cloner
{ 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
{
+16 -6
View File
@@ -83,12 +83,12 @@ void test_sizes(boolean<true>, std::size_t wordsize)
test_iterator_sizes<c>(wordsize);
}
{
typedef list< node< list_base_hook<> >, header_holder_type< pointer_holder< list_node<void*> > > > c;
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< pointer_holder< list_node<void*> > > > c;
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);
}
@@ -123,12 +123,12 @@ void test_sizes(boolean<true>, std::size_t wordsize)
test_iterator_sizes<c>(wordsize);
}
{
typedef set< node< set_base_hook<> >, header_holder_type< pointer_holder< rbtree_node<void*> > > > c;
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< pointer_holder< rbtree_node<void*> > > > c;
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);
}
@@ -148,15 +148,25 @@ void test_sizes(boolean<true>, std::size_t wordsize)
test_iterator_sizes<c>(wordsize);
}
{
typedef avl_set< node< avl_set_base_hook<> >, header_holder_type< pointer_holder< avltree_node<void*> > > > c;
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< pointer_holder< avltree_node<void*> > > > c;
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);
+58 -127
View File
@@ -15,6 +15,7 @@
#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"
@@ -23,61 +24,25 @@ namespace boost{
namespace intrusive{
namespace test{
template<class T>
struct has_splay
{
static const bool value = false;
};
BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(has_splay, splay)
template<class T>
struct has_rebalance
{
static const bool value = false;
};
BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(has_rebalance, rebalance)
template<class T>
struct has_insert_before
{
static const bool value = false;
};
BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(has_insert_before, insert_before)
template<class T>
struct has_const_searches
{
static const bool value = true;
};
BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(is_treap, priority_comp)
template<class T, bool = has_const_searches<T>::value>
struct search_const_iterator
{
typedef typename T::const_iterator type;
};
template<class T>
struct search_const_iterator<T, false>
{
typedef typename T::iterator type;
};
template<class T, bool = has_const_searches<T>::value>
struct search_const_container
{
typedef const T type;
};
template<class T>
struct search_const_container<T, false>
{
typedef T type;
};
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
struct test_generic_assoc
{
typedef typename ValueTraits::value_type value_type;
typedef typename Value_Container< value_type >::type value_cont_type;
typedef typename ValueTraits::reference reference;
typedef typename ValueTraits::const_reference const_reference;
typedef typename ValueTraits::pointer pointer;
typedef typename ValueTraits::const_pointer const_pointer;
typedef typename ValueContainer< value_type >::type value_cont_type;
typedef typename pointer_traits<pointer>::reference reference;
typedef typename pointer_traits
<const_pointer>::reference const_reference;
static void test_all(value_cont_type&);
static void test_clone(value_cont_type&);
static void test_insert_erase_burst();
@@ -95,16 +60,12 @@ struct test_generic_assoc
static void test_container_from_iterator(value_cont_type&, detail::false_type) {}
};
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_assoc<ValueTraits, ContainerDefiner>::
test_container_from_iterator(value_cont_type& values, detail::true_type)
{
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type assoc_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;
@@ -123,11 +84,9 @@ void test_generic_assoc<ValueTraits, ContainerDefiner>::
}
}
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_insert_erase_burst()
{
typedef typename ValueTraits::value_type value_type;
//value_cont_type values;
const std::size_t MaxValues = 200;
value_cont_type values(MaxValues);
@@ -135,12 +94,8 @@ void test_generic_assoc<ValueTraits, ContainerDefiner>::test_insert_erase_burst(
(&values[i])->value_ = i;
}
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type assoc_type;
typedef typename ContainerDefiner::template container
<>::type assoc_type;
typedef typename assoc_type::iterator iterator;
{ //Ordered insertion + erasure
@@ -181,16 +136,11 @@ void test_generic_assoc<ValueTraits, ContainerDefiner>::test_insert_erase_burst(
}
}
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_all(value_cont_type& values)
{
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type assoc_type;
typedef typename ContainerDefiner::template container
<>::type assoc_type;
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 >());
@@ -201,52 +151,49 @@ void test_generic_assoc<ValueTraits, ContainerDefiner>::test_all(value_cont_type
test_container_from_iterator(values, detail::bool_< assoc_type::has_container_from_iterator >());
}
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_assoc<ValueTraits, ContainerDefiner>
::test_clone(value_cont_type& values)
{
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type assoc_type;
assoc_type testset1 (values.begin(), values.begin() + values.size());
assoc_type testset2;
{
typedef typename ContainerDefiner::template container
<>::type assoc_type;
assoc_type testset1 (values.begin(), values.begin() + values.size());
assoc_type testset2;
testset2.clone_from(testset1, test::new_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());
typedef typename assoc_type::size_type size_type;
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 ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_assoc<ValueTraits, ContainerDefiner>
::test_container_from_end(value_cont_type& values, detail::true_type)
{
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type assoc_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 ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_splay_up
(value_cont_type& values, detail::true_type)
{
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type assoc_type;
typedef typename ContainerDefiner::template container
<>::type assoc_type;
typedef typename assoc_type::iterator iterator;
typedef value_cont_type orig_set_t;
@@ -276,17 +223,12 @@ void test_generic_assoc<ValueTraits, ContainerDefiner>::test_splay_up
}
}
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_splay_down
(value_cont_type& values, detail::true_type)
{
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type assoc_type;
typedef typename ContainerDefiner::template container
<>::type assoc_type;
typedef typename assoc_type::iterator iterator;
typedef value_cont_type orig_set_t;
@@ -317,23 +259,17 @@ void test_generic_assoc<ValueTraits, ContainerDefiner>::test_splay_down
}
}
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_rebalance
(value_cont_type& values, detail::true_type)
{
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type assoc_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.insert(original_testset.end(), testset.begin(), testset.end());
original_testset = value_cont_type(testset.begin(), testset.end());
original_testset.assign(testset.begin(), testset.end());
}
{
assoc_type testset(values.begin(), values.end());
@@ -358,17 +294,12 @@ void test_generic_assoc<ValueTraits, ContainerDefiner>::test_rebalance
}
}
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_insert_before
(value_cont_type& values, detail::true_type)
{
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type assoc_type;
typedef typename ContainerDefiner::template container
<>::type assoc_type;
{
assoc_type testset;
typedef typename value_cont_type::iterator vec_iterator;
+42 -72
View File
@@ -25,13 +25,17 @@ namespace boost{
namespace intrusive{
namespace test{
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
struct test_generic_multiset
{
typedef typename ValueTraits::value_type value_type;
typedef typename Value_Container< value_type >::type value_cont_type;
typedef typename ValueTraits::reference reference;
typedef typename ValueTraits::const_reference const_reference;
typedef typename ValueTraits::pointer pointer;
typedef typename ValueTraits::const_pointer const_pointer;
typedef typename ValueContainer< value_type >::type value_cont_type;
typedef typename pointer_traits<pointer>::reference reference;
typedef typename pointer_traits
<const_pointer>::reference const_reference;
static void test_all();
static void test_sort(value_cont_type&);
static void test_insert(value_cont_type&);
@@ -40,20 +44,15 @@ struct test_generic_multiset
static void test_impl();
};
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_multiset<ValueTraits, ContainerDefiner>::test_all ()
{
typedef typename ValueTraits::value_type value_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];
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type multiset_type;
typedef typename ContainerDefiner::template container
<>::type multiset_type;
{
multiset_type testset(values.begin(), values.end());
test::test_container(testset);
@@ -76,20 +75,14 @@ void test_generic_multiset<ValueTraits, ContainerDefiner>::test_all ()
}
//test case due to an error in tree implementation:
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_multiset<ValueTraits, ContainerDefiner>::test_impl()
{
typedef typename ValueTraits::value_type value_type;
value_cont_type values (5);
for (int i = 0; i < 5; ++i)
(&values[i])->value_ = i;
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type multiset_type;
typedef typename ContainerDefiner::template container
<>::type multiset_type;
multiset_type testset;
for (int i = 0; i < 5; ++i)
@@ -104,16 +97,11 @@ void test_generic_multiset<ValueTraits, ContainerDefiner>::test_impl()
}
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_multiset<ValueTraits, ContainerDefiner>::test_sort(value_cont_type& values)
{
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type multiset_type;
typedef typename ContainerDefiner::template container
<>::type multiset_type;
multiset_type testset1 (values.begin(), values.end());
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
@@ -122,13 +110,9 @@ void test_generic_multiset<ValueTraits, ContainerDefiner>::test_sort(value_cont_
testset1.clear();
BOOST_TEST (testset1.empty());
typedef ContainerDefiner
< value_type
, compare<even_odd>
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function2;
typedef typename definer_function2::type multiset_type2;
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 };
@@ -139,16 +123,11 @@ void test_generic_multiset<ValueTraits, ContainerDefiner>::test_sort(value_cont_
}
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_multiset<ValueTraits, ContainerDefiner>::test_insert(value_cont_type& values)
{
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type multiset_type;
typedef typename ContainerDefiner::template container
<>::type multiset_type;
multiset_type testset;
testset.insert(values.begin() + 2, values.begin() + 5);
@@ -177,16 +156,11 @@ void test_generic_multiset<ValueTraits, ContainerDefiner>::test_insert(value_con
}
//test: insert (seq-version), swap, erase (seq-version), size:
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_multiset<ValueTraits, ContainerDefiner>::test_swap(value_cont_type& values)
{
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type multiset_type;
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);
@@ -203,40 +177,36 @@ void test_generic_multiset<ValueTraits, ContainerDefiner>::test_swap(value_cont_
}
//test: find, equal_range (lower_bound, upper_bound):
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_multiset<ValueTraits, ContainerDefiner>::test_find(value_cont_type& values)
{
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type multiset_type;
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);
reference cmp_val = cmp_val_cont.front();
(&cmp_val)->value_ = 2;
iterator i = testset.find (cmp_val);
iterator i = testset.find (key_of_value()(cmp_val));
BOOST_TEST (i->value_ == 2);
BOOST_TEST ((++i)->value_ == 2);
std::pair<iterator,iterator> range = testset.equal_range (cmp_val);
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) == 2);
(&cmp_val)->value_ = 7;
BOOST_TEST (testset.find (cmp_val) == testset.end());
BOOST_TEST (testset.find(key_of_value()(cmp_val)) == testset.end());
}
{ //1, 2, 2, 3, 4, 5
typename search_const_container<multiset_type>::type &const_testset = testset;
const multiset_type &const_testset = testset;
std::pair<iterator,iterator> range;
std::pair<typename search_const_iterator<multiset_type>::type
,typename search_const_iterator<multiset_type>::type> const_range;
std::pair<const_iterator, const_iterator> const_range;
value_cont_type cmp_val_cont(2);
reference cmp_val_lower = cmp_val_cont.front();
reference cmp_val_upper = cmp_val_cont.back();
@@ -244,7 +214,7 @@ void test_generic_multiset<ValueTraits, ContainerDefiner>::test_find(value_cont_
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 2;
//left-closed, right-closed
range = testset.bounded_range (cmp_val_lower, cmp_val_upper, true, true);
range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), 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);
@@ -252,14 +222,14 @@ void test_generic_multiset<ValueTraits, ContainerDefiner>::test_find(value_cont_
{
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 2;
const_range = const_testset.bounded_range (cmp_val_lower, cmp_val_upper, true, false);
const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), 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 (cmp_val_lower, cmp_val_upper, true, false);
range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), 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);
@@ -267,7 +237,7 @@ void test_generic_multiset<ValueTraits, ContainerDefiner>::test_find(value_cont_
{
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 2;
const_range = const_testset.bounded_range (cmp_val_lower, cmp_val_upper, false, true);
const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), 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);
@@ -275,7 +245,7 @@ void test_generic_multiset<ValueTraits, ContainerDefiner>::test_find(value_cont_
{
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 2;
range = testset.bounded_range (cmp_val_lower, cmp_val_upper, false, false);
range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), 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);
@@ -283,7 +253,7 @@ void test_generic_multiset<ValueTraits, ContainerDefiner>::test_find(value_cont_
{
(&cmp_val_lower)->value_ = 5;
(&cmp_val_upper)->value_ = 6;
const_range = const_testset.bounded_range (cmp_val_lower, cmp_val_upper, true, false);
const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), 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);
+79 -100
View File
@@ -16,29 +16,30 @@
#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 T>
struct is_treap
{
static const bool value = false;
};
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
struct test_generic_set
{
typedef typename ValueTraits::value_type value_type;
typedef typename Value_Container< value_type >::type value_cont_type;
typedef typename ValueTraits::reference reference;
typedef typename ValueTraits::const_reference const_reference;
static void test_all();
private:
typedef typename ValueTraits::value_type value_type;
typedef typename ValueTraits::pointer pointer;
typedef typename ValueTraits::const_pointer const_pointer;
typedef typename ValueContainer< value_type >::type value_cont_type;
typedef typename pointer_traits<pointer>::reference reference;
typedef typename pointer_traits
<const_pointer>::reference const_reference;
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);
@@ -49,16 +50,11 @@ struct test_generic_set
};
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_set<ValueTraits, ContainerDefiner>::test_all()
{
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type set_type;
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);
@@ -97,21 +93,15 @@ void test_generic_set<ValueTraits, ContainerDefiner>::test_all()
}
//test case due to an error in tree implementation:
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_set<ValueTraits, ContainerDefiner>::test_impl()
{
typedef typename ValueTraits::value_type value_type;
value_cont_type values (5);
for (int i = 0; i < 5; ++i)
(&values[i])->value_ = i;
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type set_type;
typedef typename ContainerDefiner::template container
<>::type set_type;
set_type testset;
for (int i = 0; i < 5; ++i)
testset.insert (values[i]);
@@ -125,16 +115,11 @@ void test_generic_set<ValueTraits, ContainerDefiner>::test_impl()
}
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_set<ValueTraits, ContainerDefiner>::test_sort(value_cont_type& values)
{
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type set_type;
typedef typename ContainerDefiner::template container
<>::type set_type;
set_type testset1 (values.begin(), values.end());
{ int init_values [] = { 1, 2, 3, 4, 5 };
@@ -143,14 +128,8 @@ void test_generic_set<ValueTraits, ContainerDefiner>::test_sort(value_cont_type&
testset1.clear();
BOOST_TEST (testset1.empty());
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, compare<even_odd>
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function2;
typedef typename definer_function2::type set_type2;
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 };
@@ -160,16 +139,11 @@ void test_generic_set<ValueTraits, ContainerDefiner>::test_sort(value_cont_type&
}
//test: insert, const_iterator, const_reverse_iterator, erase, s_iterator_to:
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_set<ValueTraits, ContainerDefiner>::test_insert(value_cont_type& values)
{
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type set_type;
typedef typename ContainerDefiner::template container
<>::type set_type;
{
set_type testset;
testset.insert(values.begin() + 2, values.begin() + 5);
@@ -206,60 +180,69 @@ void test_generic_set<ValueTraits, ContainerDefiner>::test_insert(value_cont_typ
}
// treap version
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
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 ValueType>
struct prio_comp<ValueType, ValueType>
: priority_compare<ValueType>
{
bool operator()(const ValueType &v1, const ValueType &v2) const
{ return this->priority_compare<ValueType>::operator()(v1, v2); }
};
template<class ValueTraits, class ContainerDefiner>
void test_generic_set<ValueTraits, ContainerDefiner>::test_insert_advanced
(value_cont_type& values, detail::true_type)
{
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type set_type;
typedef typename ContainerDefiner::template container
<>::type set_type;
typedef typename set_type::key_of_value key_of_value;
typedef typename set_type::key_type key_type;
typedef typename set_type::value_type value_type;
typedef prio_comp<value_type, key_type> prio_comp_t;
{
set_type testset;
testset.insert(values.begin(), values.begin() + values.size());
value_type v(1);
typename set_type::insert_commit_data data;
BOOST_TEST (!testset.insert_check(v, testset.value_comp(), testset.priority_comp(), data).second);
BOOST_TEST (!testset.insert_check(testset.begin(), v, testset.value_comp(), testset.priority_comp(), data).second);
BOOST_TEST (!testset.insert_check(key_of_value()(v), testset.key_comp(), prio_comp_t(), data).second);
BOOST_TEST (!testset.insert_check(testset.begin(), key_of_value()(v), testset.key_comp(), prio_comp_t(), data).second);
}
}
//test: insert, const_iterator, const_reverse_iterator, erase, s_iterator_to:
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_set<ValueTraits, ContainerDefiner>::test_insert_advanced
(value_cont_type& values, detail::false_type)
{
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type set_type;
typedef typename ContainerDefiner::template container
<>::type set_type;
typedef typename set_type::key_of_value key_of_value;
{
set_type testset;
testset.insert(values.begin(), values.begin() + values.size());
value_type v(1);
typename set_type::insert_commit_data data;
BOOST_TEST (!testset.insert_check(v, testset.value_comp(), data).second);
BOOST_TEST (!testset.insert_check(testset.begin(), v, testset.value_comp(), data).second);
BOOST_TEST (!testset.insert_check(key_of_value()(v), testset.key_comp(), data).second);
BOOST_TEST (!testset.insert_check(testset.begin(), key_of_value()(v), testset.key_comp(), data).second);
}
}
//test: insert (seq-version), swap, erase (seq-version), size:
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_set<ValueTraits, ContainerDefiner>::test_swap(value_cont_type& values)
{
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type set_type;
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);
@@ -278,42 +261,38 @@ void test_generic_set<ValueTraits, ContainerDefiner>::test_swap(value_cont_type&
}
//test: find, equal_range (lower_bound, upper_bound), bounded_range:
template<class ValueTraits, template <class = void, class = void, class = void, class = void> class ContainerDefiner>
template<class ValueTraits, class ContainerDefiner>
void test_generic_set<ValueTraits, ContainerDefiner>::test_find(value_cont_type& values)
{
typedef typename ValueTraits::value_type value_type;
typedef ContainerDefiner
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> definer_function;
typedef typename definer_function::type set_type;
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;
{
//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 (cmp_val);
iterator i = testset.find(key_of_value()(cmp_val));
BOOST_TEST (i->value_ == 2);
BOOST_TEST ((++i)->value_ != 2);
std::pair<iterator,iterator> range = testset.equal_range (cmp_val);
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) == 1);
(&cmp_val)->value_ = 7;
BOOST_TEST (testset.find (cmp_val) == testset.end());
BOOST_TEST (testset.find (key_of_value()(cmp_val)) == testset.end());
}
{
typename search_const_container<set_type>::type &const_testset = testset;
const set_type &const_testset = testset;
std::pair<iterator,iterator> range;
std::pair<typename search_const_iterator<set_type>::type
,typename search_const_iterator<set_type>::type> const_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();
@@ -322,7 +301,7 @@ void test_generic_set<ValueTraits, ContainerDefiner>::test_find(value_cont_type&
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 2;
//left-closed, right-closed
range = testset.bounded_range (cmp_val_lower, cmp_val_upper, true, true);
range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), 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);
@@ -330,14 +309,14 @@ void test_generic_set<ValueTraits, ContainerDefiner>::test_find(value_cont_type&
{
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 2;
const_range = const_testset.bounded_range (cmp_val_lower, cmp_val_upper, true, false);
const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), 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 (cmp_val_lower, cmp_val_upper, true, false);
range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), 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);
@@ -345,7 +324,7 @@ void test_generic_set<ValueTraits, ContainerDefiner>::test_find(value_cont_type&
{
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 2;
const_range = const_testset.bounded_range (cmp_val_lower, cmp_val_upper, false, true);
const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), 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);
@@ -353,7 +332,7 @@ void test_generic_set<ValueTraits, ContainerDefiner>::test_find(value_cont_type&
{
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 2;
range = testset.bounded_range (cmp_val_lower, cmp_val_upper, false, false);
range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), 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);
@@ -361,7 +340,7 @@ void test_generic_set<ValueTraits, ContainerDefiner>::test_find(value_cont_type&
{
(&cmp_val_lower)->value_ = 5;
(&cmp_val_upper)->value_ = 6;
const_range = const_testset.bounded_range (cmp_val_lower, cmp_val_upper, true, false);
const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), 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);
+129 -54
View File
@@ -16,7 +16,10 @@
#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{
@@ -27,7 +30,7 @@ struct testvalue_filler
void *dummy_[3];
};
template<class Hooks, bool ConstantTimeSize>
template<class Hooks>
struct testvalue
: testvalue_filler
, Hooks::base_hook_type
@@ -36,19 +39,18 @@ struct testvalue
typename Hooks::member_hook_type node_;
typename Hooks::auto_member_hook_type auto_node_;
typename Hooks::nonhook_node_member_type nhn_member_;
int value_;
static const bool constant_time_size = ConstantTimeSize;
int_holder value_;
testvalue()
{}
testvalue(int i)
explicit testvalue(int i)
: value_(i)
{}
testvalue (const testvalue& src)
: value_ (src.value_)
: value_(src.value_)
{}
// testvalue is used in boost::container::vector and thus prev and next
@@ -82,6 +84,12 @@ struct testvalue
nhn_member_.is_linked();
}
const int_holder &get_int_holder() const
{ return value_; }
int int_value() const
{ return value_.int_value(); }
~testvalue()
{}
@@ -95,109 +103,176 @@ struct testvalue
{ return value_ != other.value_; }
friend bool operator< (int other1, const testvalue &other2)
{ return other1 < other2.value_; }
{ return other1 < other2.value_.int_; }
friend bool operator< (const testvalue &other1, int other2)
{ return other1.value_ < other2; }
{ return other1.value_.int_ < other2; }
friend bool operator== (int other1, const testvalue &other2)
{ return other1 == other2.value_; }
{ return other1 == other2.value_.int_; }
friend bool operator== (const testvalue &other1, int other2)
{ return other1.value_ == other2; }
{ return other1.value_.int_ == other2; }
friend bool operator!= (int other1, const testvalue &other2)
{ return other1 != other2.value_; }
{ return other1 != other2.value_.int_; }
friend bool operator!= (const testvalue &other1, int other2)
{ return other1.value_ != 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 < typename Node_Algorithms, class Hooks, bool ConstantTimeSize >
void swap_nodes(testvalue< Hooks, ConstantTimeSize >& lhs, testvalue< Hooks, ConstantTimeSize >& rhs)
{
lhs.swap_nodes(rhs);
}
template < typename Value_Type >
std::size_t hash_value(const Value_Type& t)
template <class Type>
bool priority_order(const Type& t1, const Type& t2)
{
boost::hash<int> hasher;
return hasher((&t)->value_);
}
template < typename Value_Type >
bool priority_order(const Value_Type& t1, const Value_Type& t2)
{
std::size_t hash1 = hash_value(t1);
std::size_t hash1 = boost::hash<int>()((&t1)->int_value());
boost::hash_combine(hash1, &t1);
std::size_t hash2 = hash_value(t2);
std::size_t hash2 = boost::hash<int>()((&t2)->int_value());
boost::hash_combine(hash2, &t2);
return hash1 < hash2;
}
template<class Hooks, bool constant_time_size>
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;
}
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, constant_time_size>& t)
(std::ostream& s, const testvalue<Hooks>& t)
{ return s << t.value_; }
struct even_odd
{
template < typename value_type_1, typename value_type_2 >
template < typename key_type_1, typename key_type_2 >
bool operator()
(const value_type_1& v1
,const value_type_2& v2) const
(const key_type_1& v1
,const key_type_2& v2) const
{
if (((&v1)->value_ & 1) == ((&v2)->value_ & 1))
return (&v1)->value_ < (&v2)->value_;
if (((&v1)->int_value() & 1) == ((&v2)->int_value() & 1))
return (&v1)->int_value() < (&v2)->int_value();
else
return (&v2)->value_ & 1;
return (&v2)->int_value() & 1;
}
};
struct is_even
{
template <typename value_type>
template <typename key_type>
bool operator()
(const value_type& v1) const
{ return ((&v1)->value_ & 1) == 0; }
(const key_type& v1) const
{ return ((&v1)->int_value() & 1) == 0; }
};
struct is_odd
{
template <typename value_type>
template <typename key_type>
bool operator()
(const value_type& v1) const
{ return ((&v1)->value_ & 1) != 0; }
(const key_type& v1) const
{ return ((&v1)->int_value() & 1) != 0; }
};
template <typename>
struct Value_Container;
struct ValueContainer;
template < class Hooks, bool ConstantTimeSize >
struct Value_Container< testvalue< Hooks, ConstantTimeSize > >
template < class Hooks>
struct ValueContainer< testvalue<Hooks> >
{
typedef boost::container::vector< testvalue< Hooks, ConstantTimeSize > > type;
typedef boost::container::vector< testvalue<Hooks> > type;
};
template < typename T >
class pointer_holder
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:
pointer_holder() : _ptr(new T())
heap_node_holder()
: m_ptr(pointer_traits<Pointer>::pointer_to(*new element_type))
{}
~pointer_holder()
{ delete _ptr; }
~heap_node_holder()
{ delete &*m_ptr; }
const T* get_node() const { return _ptr; }
T* get_node() { return _ptr; }
const_pointer get_node() const
{ return m_ptr; }
pointer get_node()
{ return m_ptr; }
private:
T* const _ptr;
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 boost{
} //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
+60 -63
View File
@@ -24,15 +24,13 @@
using namespace boost::intrusive;
class my_tag;
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<my_tag> > auto_base_hook_type;
typedef list_member_hook<void_pointer<VoidPointer>, tag<my_tag> > member_hook_type;
, 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 >,
@@ -40,29 +38,29 @@ struct hooks
};
template < typename List_Type, typename Value_Container >
template < typename ListType, typename ValueContainer >
struct test_list
{
typedef List_Type list_type;
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(Value_Container&);
static void test_front_back(Value_Container&);
static void test_sort(Value_Container&);
static void test_merge(Value_Container&);
static void test_remove_unique(Value_Container&);
static void test_insert(Value_Container&);
static void test_shift(Value_Container&);
static void test_swap(Value_Container&);
static void test_clone(Value_Container&);
static void test_container_from_end(Value_Container&, detail::true_type);
static void test_container_from_end(Value_Container&, detail::false_type) {}
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 List_Type, typename Value_Container >
void test_list< List_Type, Value_Container >::test_all(Value_Container& values)
template < typename ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >::test_all(ValueContainer& values)
{
{
list_type list(values.begin(), values.end());
@@ -84,13 +82,13 @@ void test_list< List_Type, Value_Container >::test_all(Value_Container& values)
test_shift(values);
test_swap(values);
test_clone(values);
test_container_from_end(values, detail::bool_< List_Type::has_container_from_iterator >());
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 List_Type, typename Value_Container >
void test_list< List_Type, Value_Container >
::test_front_back(Value_Container& values)
template < class ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >
::test_front_back(ValueContainer& values)
{
list_type testlist;
BOOST_TEST (testlist.empty());
@@ -116,9 +114,9 @@ void test_list< List_Type, Value_Container >
}
//test: constructor, iterator, reverse_iterator, sort, reverse:
template < class List_Type, typename Value_Container >
void test_list< List_Type, Value_Container >
::test_sort(Value_Container& values)
template < class ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >
::test_sort(ValueContainer& values)
{
list_type testlist(values.begin(), values.end());
@@ -135,9 +133,9 @@ void test_list< List_Type, Value_Container >
}
//test: merge due to error in merge implementation:
template < class List_Type, typename Value_Container >
void test_list< List_Type, Value_Container >
::test_remove_unique (Value_Container& values)
template < class ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >
::test_remove_unique (ValueContainer& values)
{
{
list_type list(values.begin(), values.end());
@@ -164,7 +162,7 @@ void test_list< List_Type, Value_Container >
TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
}
{
Value_Container values2(values);
ValueContainer values2(values);
list_type list(values.begin(), values.end());
list.insert(list.end(), values2.begin(), values2.end());
list.sort();
@@ -177,9 +175,9 @@ void test_list< List_Type, Value_Container >
}
//test: merge due to error in merge implementation:
template < class List_Type, typename Value_Container >
void test_list< List_Type, Value_Container >
::test_merge (Value_Container& values)
template < class ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >
::test_merge (ValueContainer& values)
{
list_type testlist1, testlist2;
testlist1.push_front (values[0]);
@@ -193,9 +191,9 @@ void test_list< List_Type, Value_Container >
}
//test: assign, insert, const_iterator, const_reverse_iterator, erase, s_iterator_to:
template < class List_Type, typename Value_Container >
void test_list< List_Type, Value_Container >
::test_insert(Value_Container& values)
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);
@@ -236,9 +234,9 @@ void test_list< List_Type, Value_Container >
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
}
template < class List_Type, typename Value_Container >
void test_list< List_Type, Value_Container >
::test_shift(Value_Container& values)
template < class ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >
::test_shift(ValueContainer& values)
{
list_type testlist;
const int num_values = (int)values.size();
@@ -271,9 +269,9 @@ void test_list< List_Type, Value_Container >
}
//test: insert (seq-version), swap, splice, erase (seq-version):
template < class List_Type, typename Value_Container >
void test_list< List_Type, Value_Container >
::test_swap(Value_Container& values)
template < class ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >
::test_swap(ValueContainer& values)
{
{
list_type testlist1 (values.begin(), values.begin() + 2);
@@ -347,18 +345,18 @@ void test_list< List_Type, Value_Container >
}
}
template < class List_Type, typename Value_Container >
void test_list< List_Type, Value_Container >
::test_container_from_end(Value_Container& values, detail::true_type)
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 List_Type, typename Value_Container >
void test_list< List_Type, Value_Container >
::test_clone(Value_Container& values)
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;
@@ -369,26 +367,26 @@ void test_list< List_Type, Value_Container >
BOOST_TEST (testlist2.empty());
}
template < typename Value_Traits, bool ConstantTimeSize, bool Default_Holder, typename Value_Container >
template < typename ValueTraits, bool ConstantTimeSize, bool Default_Holder, typename ValueContainer >
struct make_and_test_list
: test_list< list< typename Value_Traits::value_type,
value_traits< Value_Traits >,
: test_list< list< typename ValueTraits::value_type,
value_traits< ValueTraits >,
size_type< std::size_t >,
constant_time_size< ConstantTimeSize >
>,
Value_Container
ValueContainer
>
{};
template < typename Value_Traits, bool ConstantTimeSize, typename Value_Container >
struct make_and_test_list< Value_Traits, ConstantTimeSize, false, Value_Container >
: test_list< list< typename Value_Traits::value_type,
value_traits< Value_Traits >,
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< pointer_holder< typename Value_Traits::node_traits::node > >
header_holder_type< heap_node_holder< typename ValueTraits::pointer > >
>,
Value_Container
ValueContainer
>
{};
@@ -399,7 +397,7 @@ class test_main_template
public:
int operator()()
{
typedef testvalue<hooks<VoidPointer>, ConstantTimeSize> value_type;
typedef testvalue< hooks<VoidPointer> > value_type;
std::vector<value_type> data (5);
for (int i = 0; i < 5; ++i)
data[i].value_ = i + 1;
@@ -440,7 +438,7 @@ class test_main_template< VoidPointer, false, Default_Holder >
public:
int operator()()
{
typedef testvalue<hooks<VoidPointer>, false> value_type;
typedef testvalue< hooks<VoidPointer> > value_type;
std::vector<value_type> data (5);
for (int i = 0; i < 5; ++i)
data[i].value_ = i + 1;
@@ -503,7 +501,8 @@ struct test_main_template_bptr
typedef typename list_value_traits::node_ptr node_ptr;
typedef bounded_allocator< value_type > allocator_type;
allocator_type::init();
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
allocator_type allocator;
{
@@ -525,8 +524,6 @@ struct test_main_template_bptr
>::test_all(ref_cont);
}
assert(allocator_type::is_clear());
allocator_type::destroy();
return 0;
}
};
+13 -1
View File
@@ -16,6 +16,7 @@
#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>
@@ -27,6 +28,7 @@ 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>
@@ -34,6 +36,9 @@ typedef make_bs_set_base_hook
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
@@ -50,6 +55,7 @@ class MyClass
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type
, public TreapHook
, public SplayHook
, public BsHook
{
int int_;
@@ -83,6 +89,8 @@ 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()
{
@@ -103,6 +111,7 @@ int main()
AvlSet my_avlset;
SplaySet my_splayset;
BsSet my_bsset;
SgSet my_sgset;
TreapSet my_treapset;
@@ -114,6 +123,7 @@ int main()
my_uset.insert(*it);
my_avlset.insert(*it);
my_splayset.insert(*it);
my_bsset.insert(*it);
my_sgset.insert(*it);
my_treapset.insert(*it);
}
@@ -126,6 +136,7 @@ int main()
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());
@@ -134,7 +145,7 @@ int main()
//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, ++sgset_rit, ++treapset_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;
@@ -142,6 +153,7 @@ int main()
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;
}
+90 -204
View File
@@ -1,7 +1,7 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2013.
// (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
@@ -14,230 +14,116 @@
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "rb_test_common.hpp"
#include "generic_multiset_test.hpp"
namespace boost { namespace intrusive { namespace test {
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct has_insert_before<boost::intrusive::multiset<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = true;
};
}}}
using namespace boost::intrusive;
struct my_tag;
template<class VoidPointer>
struct hooks
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef set_base_hook
<void_pointer<VoidPointer> > base_hook_type;
typedef set_base_hook
<link_mode<auto_unlink>
, void_pointer<VoidPointer>
, tag<my_tag>
, 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, false >,
rbtree_algorithms
> nonhook_node_member_type;
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
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));
};
};
// container generator with void node allocator
template < bool Default_Holder >
struct GetContainer_With_Holder
{
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainer
{
typedef boost::intrusive::multiset
< ValueType
, Option1
, Option2
, Option3
> type;
};
};
// 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< rbtree_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::multiset
< ValueType
, Option1
, Option2
, Option3
, header_holder_type< pointer_holder< node > >
> type;
};
};
template<class VoidPointer, bool constant_time_size, bool Default_Holder>
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template
{
public:
int operator()()
static void execute()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , constant_time_size> value_type;
test::test_generic_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < nonhook_node_member_value_traits< value_type,
typename hooks<VoidPointer>::nonhook_node_member_type,
&value_type::nhn_member_,
safe_link
>,
GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
return 0;
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
< base_hook_t
, rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
//member
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::member_value_traits
, typename testval_traits_t::auto_member_value_traits
>::type member_hook_t;
test::test_generic_multiset
< member_hook_t
, rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
//nonmember
test::test_generic_multiset
< typename testval_traits_t::nonhook_value_traits
, rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool Default_Holder>
class test_main_template<VoidPointer, false, Default_Holder>
{
public:
int operator()()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , false> value_type;
test::test_generic_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::auto_base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::auto_member_hook_type
, &value_type::auto_node_
>
>::type
, 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 ConstantTimeSize, typename HeaderHolder >
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< rbtree_defaults, Option1, Option2, Option3 >::type packed_options;
typedef typename packed_options::compare compare_option;
typedef boost::intrusive::multiset< typename Value_Traits::value_type,
value_traits< Value_Traits >,
constant_time_size< ConstantTimeSize >,
compare< compare_option >,
header_holder_type< HeaderHolder >
> type;
};
};
template < bool ConstantTimeSize >
template < bool ConstantTimeSize, bool Map >
struct test_main_template_bptr
{
void operator () ()
{
typedef BPtr_Value value_type;
typedef BPtr_Value_Traits< RBTree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< value_type > allocator_type;
static void execute()
{
typedef BPtr_Value_Traits< RBTree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
allocator_type::init();
test::test_generic_multiset< value_traits,
Get_Preset_Container< value_traits, ConstantTimeSize,
bounded_pointer_holder< value_type > >::template GetContainer
>::test_all();
assert(allocator_type::is_clear());
allocator_type::destroy();
}
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_multiset
< value_traits
, rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
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 >()();
//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>::execute();
test_main_template<void*, false, false, true>::execute();
//test_main_template<void*, false, true, false>::execute();
test_main_template<void*, false, true, true>::execute();
//test_main_template<void*, true, false, false>::execute();
test_main_template<void*, true, false, true>::execute();
//test_main_template<void*, true, true, false>::execute();
test_main_template<void*, true, true, true>::execute();
//smart_ptr
test_main_template<smart_ptr<void>, false, false, false>::execute();
//test_main_template<smart_ptr<void>, false, false, true>::execute();
test_main_template<smart_ptr<void>, false, true, false>::execute();
//test_main_template<smart_ptr<void>, false, true, true>::execute();
test_main_template<smart_ptr<void>, true, false, false>::execute();
//test_main_template<smart_ptr<void>, true, false, true>::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();
}
+2
View File
@@ -17,6 +17,8 @@
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/static_assert.hpp>
#include <boost/intrusive/detail/to_raw_pointer.hpp>
#include <boost/intrusive/detail/parent_from_member.hpp>
namespace boost{
+90 -206
View File
@@ -1,7 +1,7 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2013.
// (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
@@ -14,232 +14,116 @@
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "rb_test_common.hpp"
#include "generic_set_test.hpp"
namespace boost { namespace intrusive { namespace test {
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct has_insert_before<boost::intrusive::set<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = true;
};
}}}
struct my_tag;
using namespace boost::intrusive;
template<class VoidPointer>
struct hooks
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef set_base_hook
<void_pointer<VoidPointer> > base_hook_type;
typedef set_base_hook
<link_mode<auto_unlink>
, void_pointer<VoidPointer>
, tag<my_tag>
, 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, false >,
rbtree_algorithms
> nonhook_node_member_type;
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
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));
};
};
// container generator with void node allocator
template < bool Default_Holder >
struct GetContainer_With_Holder
{
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainer
{
typedef boost::intrusive::set
< ValueType
, Option1
, Option2
, Option3
> type;
};
};
// 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< rbtree_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::set
< ValueType
, Option1
, Option2
, Option3
, header_holder_type< pointer_holder< node > >
> type;
};
};
template<class VoidPointer, bool constant_time_size, bool Default_Holder>
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template
{
public:
int operator()()
static void execute()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , constant_time_size> value_type;
test::test_generic_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < nonhook_node_member_value_traits< value_type,
typename hooks<VoidPointer>::nonhook_node_member_type,
&value_type::nhn_member_,
safe_link
>,
GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
return 0;
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
< base_hook_t
, rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
//member
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::member_value_traits
, typename testval_traits_t::auto_member_value_traits
>::type member_hook_t;
test::test_generic_set
< member_hook_t
, rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
//nonmember
test::test_generic_set
< typename testval_traits_t::nonhook_value_traits
, rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool Default_Holder>
class test_main_template<VoidPointer, false, Default_Holder>
{
public:
int operator()()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , false> value_type;
test::test_generic_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::auto_base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::auto_member_hook_type
, &value_type::auto_node_
>
>::type
, 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 ConstantTimeSize, typename HeaderHolder >
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< rbtree_defaults, Option1, Option2, Option3 >::type packed_options;
typedef typename packed_options::compare compare_option;
typedef boost::intrusive::set< typename Value_Traits::value_type,
value_traits< Value_Traits >,
constant_time_size< ConstantTimeSize >,
compare< compare_option >,
header_holder_type< HeaderHolder >
> type;
};
};
template < bool ConstantTimeSize >
template < bool ConstantTimeSize, bool Map >
struct test_main_template_bptr
{
void operator () ()
{
typedef BPtr_Value value_type;
typedef BPtr_Value_Traits< RBTree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< value_type > allocator_type;
static void execute()
{
typedef BPtr_Value_Traits< RBTree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
allocator_type::init();
test::test_generic_set< value_traits,
Get_Preset_Container< value_traits, ConstantTimeSize,
bounded_pointer_holder< value_type >
>::template GetContainer
>::test_all();
assert(allocator_type::is_clear());
allocator_type::destroy();
}
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_set
< value_traits
, rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
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 >()();
//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>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false>::execute();
//test_main_template<void*, true, true, true>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true>::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();
}
+82 -262
View File
@@ -1,7 +1,6 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2013.
// (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
@@ -14,287 +13,108 @@
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "bs_test_common.hpp"
#include "generic_multiset_test.hpp"
namespace boost { namespace intrusive { namespace test {
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct has_rebalance<boost::intrusive::sg_multiset<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = true;
};
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct has_insert_before<boost::intrusive::sg_multiset<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = true;
};
}}}
using namespace boost::intrusive;
struct my_tag;
template<class VoidPointer>
struct hooks
template < class ValueTraits, bool FloatingPoint, bool DefaultHolder, bool Map >
struct rebinder
{
typedef bs_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
typedef bs_set_member_hook<void_pointer<VoidPointer> > member_hook_type;
typedef member_hook_type auto_member_hook_type;
struct auto_base_hook_type
: bs_set_base_hook<void_pointer<VoidPointer>, tag<my_tag> >
{};
typedef nonhook_node_member< tree_node_traits < VoidPointer >,
sgtree_algorithms
> nonhook_node_member_type;
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
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));
};
};
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainer
{
typedef boost::intrusive::sg_set
< ValueType
, Option1
, Option2
, Option3
> type;
};
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainerFixedAlpha
{
typedef boost::intrusive::sg_set
< ValueType
, Option1
, Option2
, Option3
, boost::intrusive::floating_point<false>
> type;
};
// container generator with void node allocator
template < bool Default_Holder >
struct GetContainer_With_Holder
{
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainer
{
typedef boost::intrusive::sg_multiset
< ValueType
, Option1
, Option2
, Option3
> type;
};
};
// 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< sgtree_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::sg_multiset
< ValueType
, Option1
, Option2
, Option3
, header_holder_type< pointer_holder< node > >
> type;
};
};
// container generator with void node allocator
template < bool Default_Holder >
struct GetContainerFixedAlpha_With_Holder
{
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainerFixedAlpha
{
typedef boost::intrusive::sg_multiset
< ValueType
, Option1
, Option2
, Option3
> type;
};
};
// container generator with standard (non-void) node allocator
template <>
struct GetContainerFixedAlpha_With_Holder< false >
{
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainerFixedAlpha
{
// extract node type through options->value_traits->node_traits->node
typedef typename pack_options< sgtree_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::sg_multiset
< ValueType
, Option1
, Option2
, Option3
, boost::intrusive::floating_point<false>
, header_holder_type< pointer_holder< node > >
> type;
};
};
template<class VoidPointer, bool Default_Holder>
template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map>
class test_main_template
{
public:
int operator()()
static void execute()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , true> value_type;
test::test_generic_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainerFixedAlpha_With_Holder< Default_Holder >::template GetContainerFixedAlpha
>::test_all();
test::test_generic_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainerFixedAlpha_With_Holder< Default_Holder >::template GetContainerFixedAlpha
>::test_all();
test::test_generic_multiset < nonhook_node_member_value_traits< value_type,
typename hooks<VoidPointer>::nonhook_node_member_type,
&value_type::nhn_member_,
safe_link
>,
GetContainerFixedAlpha_With_Holder< Default_Holder >::template GetContainerFixedAlpha
>::test_all();
return 0;
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
< base_hook_t
, rebinder<base_hook_t, FloatingPoint, DefaultHolder, Map>
>::test_all();
//member
typedef typename testval_traits_t::member_value_traits member_hook_t;
test::test_generic_multiset
< member_hook_t
, rebinder<member_hook_t, FloatingPoint, DefaultHolder, Map>
>::test_all();
//nonmember
test::test_generic_multiset
< typename testval_traits_t::nonhook_value_traits
, rebinder<typename testval_traits_t::nonhook_value_traits, FloatingPoint, DefaultHolder, Map>
>::test_all();
}
};
// container generator which ignores further parametrization, except for compare option
template < typename Value_Traits, bool ConstantTimeSize, typename HeaderHolder >
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< sgtree_defaults, Option1, Option2, Option3 >::type packed_options;
typedef typename packed_options::compare compare_option;
typedef boost::intrusive::sg_multiset< typename Value_Traits::value_type,
value_traits< Value_Traits >,
constant_time_size< ConstantTimeSize >,
compare< compare_option >,
header_holder_type< HeaderHolder >
> type;
};
};
template < bool FloatingPoint, bool Map >
struct test_main_template_bptr
{
void operator () ()
{
typedef BPtr_Value value_type;
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< value_type > allocator_type;
static void execute()
{
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
allocator_type::init();
test::test_generic_multiset< value_traits,
Get_Preset_Container< value_traits, true,
bounded_pointer_holder< value_type > >::GetContainer
>::test_all();
assert(allocator_type::is_clear());
allocator_type::destroy();
}
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_multiset
< value_traits
, rebinder< value_traits, FloatingPoint, true, Map>
>::test_all();
}
};
int main()
{
// test (plain/smart pointers) x (const size) x (void node allocator)
test_main_template<void*, true>()();
test_main_template<boost::intrusive::smart_ptr<void>, true >()();
// test (bounded pointers) x (nonconst/const size) x (special node allocator)
test_main_template_bptr()();
//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>::execute();
test_main_template<void*, false, false, true>::execute();
//test_main_template<void*, false, true, false>::execute();
test_main_template<void*, false, true, true>::execute();
//test_main_template<void*, true, false, false>::execute();
test_main_template<void*, true, false, true>::execute();
//test_main_template<void*, true, true, false>::execute();
test_main_template<void*, true, true, true>::execute();
//smart_ptr
test_main_template<smart_ptr<void>, false, false, false>::execute();
//test_main_template<smart_ptr<void>, false, false, true>::execute();
test_main_template<smart_ptr<void>, false, true, false>::execute();
//test_main_template<smart_ptr<void>, false, true, true>::execute();
test_main_template<smart_ptr<void>, true, false, false>::execute();
//test_main_template<smart_ptr<void>, true, false, true>::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();
}
+81 -261
View File
@@ -13,288 +13,108 @@
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "bs_test_common.hpp"
#include "generic_set_test.hpp"
namespace boost { namespace intrusive { namespace test {
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct has_rebalance<boost::intrusive::sg_set<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = true;
};
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct has_insert_before<boost::intrusive::sg_set<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = true;
};
}}}
using namespace boost::intrusive;
struct my_tag;
template<class VoidPointer>
struct hooks
template < class ValueTraits, bool FloatingPoint, bool DefaultHolder, bool Map >
struct rebinder
{
typedef bs_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
typedef bs_set_member_hook<void_pointer<VoidPointer> > member_hook_type;
typedef member_hook_type auto_member_hook_type;
struct auto_base_hook_type
: bs_set_base_hook<void_pointer<VoidPointer>, tag<my_tag> >
{};
typedef nonhook_node_member< tree_node_traits < VoidPointer >,
sgtree_algorithms
> nonhook_node_member_type;
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
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));
};
};
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainer
{
typedef boost::intrusive::sg_set
< ValueType
, Option1
, Option2
, Option3
> type;
};
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainerFixedAlpha
{
typedef boost::intrusive::sg_set
< ValueType
, Option1
, Option2
, Option3
, boost::intrusive::floating_point<false>
> type;
};
// container generator with void node allocator
template < bool Default_Holder >
struct GetContainer_With_Holder
{
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainer
{
typedef boost::intrusive::sg_set
< ValueType
, Option1
, Option2
, Option3
> type;
};
};
// 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< sgtree_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::sg_set
< ValueType
, Option1
, Option2
, Option3
, header_holder_type< pointer_holder< node > >
> type;
};
};
// container generator with void node allocator
template < bool Default_Holder >
struct GetContainerFixedAlpha_With_Holder
{
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainerFixedAlpha
{
typedef boost::intrusive::sg_set
< ValueType
, Option1
, Option2
, Option3
> type;
};
};
// container generator with standard (non-void) node allocator
template <>
struct GetContainerFixedAlpha_With_Holder< false >
{
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainerFixedAlpha
{
// extract node type through options->value_traits->node_traits->node
typedef typename pack_options< sgtree_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::sg_set
< ValueType
, Option1
, Option2
, Option3
, boost::intrusive::floating_point<false>
, header_holder_type< pointer_holder< node > >
> type;
};
};
template<class VoidPointer, bool Default_Holder>
template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map>
class test_main_template
{
public:
int operator()()
static void execute()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , true> value_type;
test::test_generic_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainerFixedAlpha_With_Holder< Default_Holder >::template GetContainerFixedAlpha
>::test_all();
test::test_generic_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainerFixedAlpha_With_Holder< Default_Holder >::template GetContainerFixedAlpha
>::test_all();
test::test_generic_set < nonhook_node_member_value_traits< value_type,
typename hooks<VoidPointer>::nonhook_node_member_type,
&value_type::nhn_member_,
safe_link
>,
GetContainerFixedAlpha_With_Holder< Default_Holder >::template GetContainerFixedAlpha
>::test_all();
return 0;
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
< base_hook_t
, rebinder<base_hook_t, FloatingPoint, DefaultHolder, Map>
>::test_all();
//member
typedef typename testval_traits_t::member_value_traits member_hook_t;
test::test_generic_set
< member_hook_t
, rebinder<member_hook_t, FloatingPoint, DefaultHolder, Map>
>::test_all();
//nonmember
test::test_generic_set
< typename testval_traits_t::nonhook_value_traits
, rebinder<typename testval_traits_t::nonhook_value_traits, FloatingPoint, DefaultHolder, Map>
>::test_all();
}
};
// container generator which ignores further parametrization, except for compare option
template < typename Value_Traits, bool ConstantTimeSize, typename HeaderHolder >
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< sgtree_defaults, Option1, Option2, Option3 >::type packed_options;
typedef typename packed_options::compare compare_option;
typedef boost::intrusive::sg_set< typename Value_Traits::value_type,
value_traits< Value_Traits >,
constant_time_size< ConstantTimeSize >,
compare< compare_option >,
header_holder_type< HeaderHolder >
> type;
};
};
template < bool FloatingPoint, bool Map >
struct test_main_template_bptr
{
void operator () ()
{
typedef BPtr_Value value_type;
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< value_type > allocator_type;
static void execute()
{
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
allocator_type::init();
test::test_generic_set< value_traits,
Get_Preset_Container< value_traits, true,
bounded_pointer_holder< value_type > >::GetContainer
>::test_all();
assert(allocator_type::is_clear());
allocator_type::destroy();
}
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_set
< value_traits
, rebinder< value_traits, FloatingPoint, true, Map>
>::test_all();
}
};
int main()
{
// test (plain/smart pointers) x (const size) x (void node allocator)
test_main_template<void*, true>()();
test_main_template<boost::intrusive::smart_ptr<void>, true >()();
// test (plain pointers) x (const size) x (standard node allocator)
test_main_template<void*, false>()();
// test (bounded pointers) x (nonconst/const size) x (special node allocator)
test_main_template_bptr()();
//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>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false>::execute();
//test_main_template<void*, true, true, true>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true>::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();
}
+68 -73
View File
@@ -25,15 +25,13 @@
using namespace boost::intrusive;
struct my_tag;
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<my_tag> > auto_base_hook_type;
typedef slist_member_hook<void_pointer<VoidPointer>, tag<my_tag> > member_hook_type;
, 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 >,
@@ -41,33 +39,33 @@ struct hooks
> nonhook_node_member_type;
};
template < typename List_Type, typename Value_Container >
template < typename ListType, typename ValueContainer >
struct test_slist
{
typedef List_Type list_type;
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(Value_Container&);
static void test_front(Value_Container&);
static void test_back(Value_Container&, detail::true_type);
static void test_back(Value_Container&, detail::false_type) {}
static void test_sort(Value_Container&);
static void test_merge(Value_Container&);
static void test_remove_unique(Value_Container&);
static void test_insert(Value_Container&);
static void test_shift(Value_Container&);
static void test_swap(Value_Container&);
static void test_slow_insert(Value_Container&);
static void test_clone(Value_Container&);
static void test_container_from_end(Value_Container&, detail::true_type);
static void test_container_from_end(Value_Container&, detail::false_type) {}
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 List_Type, typename Value_Container >
void test_slist< List_Type, Value_Container >
::test_all (Value_Container& values)
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_all (ValueContainer& values)
{
{
list_type list(values.begin(), values.end());
@@ -94,9 +92,9 @@ void test_slist< List_Type, Value_Container >
}
//test: push_front, pop_front, front, size, empty:
template < typename List_Type, typename Value_Container >
void test_slist< List_Type, Value_Container >
::test_front(Value_Container& values)
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_front(ValueContainer& values)
{
list_type testlist;
BOOST_TEST (testlist.empty());
@@ -118,9 +116,9 @@ void test_slist< List_Type, Value_Container >
}
//test: push_front, pop_front, front, size, empty:
template < typename List_Type, typename Value_Container >
void test_slist< List_Type, Value_Container >
::test_back(Value_Container& values, detail::true_type)
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_back(ValueContainer& values, detail::true_type)
{
list_type testlist;
BOOST_TEST (testlist.empty());
@@ -136,9 +134,9 @@ void test_slist< List_Type, Value_Container >
}
//test: merge due to error in merge implementation:
template < typename List_Type, typename Value_Container >
void test_slist< List_Type, Value_Container >
::test_merge (Value_Container& values)
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_merge (ValueContainer& values)
{
list_type testlist1, testlist2;
testlist1.push_front (values[0]);
@@ -152,9 +150,9 @@ void test_slist< List_Type, Value_Container >
}
//test: merge due to error in merge implementation:
template < typename List_Type, typename Value_Container >
void test_slist< List_Type, Value_Container >
::test_remove_unique (Value_Container& values)
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_remove_unique (ValueContainer& values)
{
{
list_type list(values.begin(), values.end());
@@ -181,7 +179,7 @@ void test_slist< List_Type, Value_Container >
TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
}
{
Value_Container values2(values);
ValueContainer values2(values);
list_type list(values.begin(), values.end());
list.insert_after(list.before_begin(), values2.begin(), values2.end());
list.sort();
@@ -194,9 +192,9 @@ void test_slist< List_Type, Value_Container >
}
//test: constructor, iterator, sort, reverse:
template < typename List_Type, typename Value_Container >
void test_slist< List_Type, Value_Container >
::test_sort(Value_Container& values)
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_sort(ValueContainer& values)
{
list_type testlist (values.begin(), values.end());
@@ -213,9 +211,9 @@ void test_slist< List_Type, Value_Container >
}
//test: assign, insert_after, const_iterator, erase_after, s_iterator_to, previous:
template < typename List_Type, typename Value_Container >
void test_slist< List_Type, Value_Container >
::test_insert(Value_Container& values)
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);
@@ -252,9 +250,9 @@ void test_slist< List_Type, Value_Container >
}
//test: insert, const_iterator, erase, siterator_to:
template < typename List_Type, typename Value_Container >
void test_slist< List_Type, Value_Container >
::test_slow_insert (Value_Container& values)
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_slow_insert (ValueContainer& values)
{
list_type testlist;
testlist.push_front (values[4]);
@@ -288,9 +286,9 @@ void test_slist< List_Type, Value_Container >
BOOST_TEST (testlist.begin()->value_ == 3);
}
template < typename List_Type, typename Value_Container >
void test_slist< List_Type, Value_Container >
::test_shift(Value_Container& values)
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_shift(ValueContainer& values)
{
list_type testlist;
const int num_values = (int)values.size();
@@ -325,9 +323,9 @@ void test_slist< List_Type, Value_Container >
}
//test: insert_after (seq-version), swap, splice_after:
template < typename List_Type, typename Value_Container >
void test_slist< List_Type, Value_Container >
::test_swap(Value_Container& values)
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_swap(ValueContainer& values)
{
{
list_type testlist1 (values.begin(), values.begin() + 2);
@@ -426,9 +424,9 @@ void test_slist< List_Type, Value_Container >
}
}
template < typename List_Type, typename Value_Container >
void test_slist< List_Type, Value_Container >
::test_clone(Value_Container& values)
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;
@@ -439,39 +437,39 @@ void test_slist< List_Type, Value_Container >
BOOST_TEST (testlist2.empty());
}
template < typename List_Type, typename Value_Container >
void test_slist< List_Type, Value_Container >
::test_container_from_end(Value_Container& values, detail::true_type)
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 Value_Traits, bool ConstantTimeSize, bool Linear, bool CacheLast, bool Default_Holder, typename Value_Container >
template < typename ValueTraits, bool ConstantTimeSize, bool Linear, bool CacheLast, bool Default_Holder, typename ValueContainer >
struct make_and_test_slist
: test_slist< slist< typename Value_Traits::value_type,
value_traits< Value_Traits >,
: test_slist< slist< typename ValueTraits::value_type,
value_traits< ValueTraits >,
size_type< std::size_t >,
constant_time_size< ConstantTimeSize >,
linear<Linear>,
cache_last<CacheLast>
>,
Value_Container
ValueContainer
>
{};
template < typename Value_Traits, bool ConstantTimeSize, bool Linear, bool CacheLast, typename Value_Container >
struct make_and_test_slist< Value_Traits, ConstantTimeSize, Linear, CacheLast, false, Value_Container >
: test_slist< slist< typename Value_Traits::value_type,
value_traits< Value_Traits >,
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< pointer_holder< typename Value_Traits::node_traits::node > >
header_holder_type< heap_node_holder< typename ValueTraits::pointer > >
>,
Value_Container
ValueContainer
>
{};
@@ -481,7 +479,7 @@ class test_main_template
public:
int operator()()
{
typedef testvalue<hooks<VoidPointer> , constant_time_size> value_type;
typedef testvalue< hooks<VoidPointer> > value_type;
std::vector< value_type > data (5);
for (int i = 0; i < 5; ++i)
data[i].value_ = i + 1;
@@ -603,7 +601,7 @@ class test_main_template<VoidPointer, false, Default_Holder>
public:
int operator()()
{
typedef testvalue<hooks<VoidPointer> , false> value_type;
typedef testvalue< hooks<VoidPointer> > value_type;
std::vector< value_type > data (5);
for (int i = 0; i < 5; ++i)
data[i].value_ = i + 1;
@@ -742,7 +740,7 @@ struct test_main_template_bptr
typedef typename list_value_traits::node_ptr node_ptr;
typedef bounded_allocator< value_type > allocator_type;
allocator_type::init();
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
allocator_type allocator;
{
@@ -763,9 +761,6 @@ struct test_main_template_bptr
bounded_reference_cont< value_type >
>::test_all(ref_cont);
}
assert(allocator_type::is_clear());
allocator_type::destroy();
return 0;
}
};
+82 -237
View File
@@ -1,7 +1,6 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2013.
// (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
@@ -11,265 +10,111 @@
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/splay_set.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "bs_test_common.hpp"
#include "generic_multiset_test.hpp"
namespace boost { namespace intrusive { namespace test {
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct has_splay<boost::intrusive::splay_multiset<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = true;
};
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct has_rebalance<boost::intrusive::splay_multiset<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = true;
};
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct has_const_searches<boost::intrusive::splay_multiset<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = true;
};
}}}
using namespace boost::intrusive;
struct my_tag;
template<class VoidPointer>
struct hooks
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef bs_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
typedef bs_set_base_hook
< link_mode<auto_unlink>
, void_pointer<VoidPointer>
, tag<my_tag> > 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 >,
splaytree_algorithms
> nonhook_node_member_type;
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
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));
};
};
// container generator with void node allocator
template < bool Default_Holder >
struct GetContainer_With_Holder
{
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainer
{
typedef boost::intrusive::splay_multiset
< ValueType
, Option1
, Option2
, Option3
> type;
};
};
// 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< splaytree_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::splay_multiset
< ValueType
, Option1
, Option2
, Option3
, header_holder_type< pointer_holder< node > >
> type;
};
};
template<class VoidPointer, bool constant_time_size, bool Default_Holder>
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template
{
public:
int operator()()
static void execute()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , constant_time_size> value_type;
test::test_generic_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < nonhook_node_member_value_traits< value_type,
typename hooks<VoidPointer>::nonhook_node_member_type,
&value_type::nhn_member_,
safe_link
>,
GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
return 0;
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
< base_hook_t
, rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
//member
typedef typename testval_traits_t::member_value_traits member_hook_t;
test::test_generic_multiset
< member_hook_t
, rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
//nonmember
test::test_generic_multiset
< typename testval_traits_t::nonhook_value_traits
, rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool Default_Holder>
class test_main_template<VoidPointer, false, Default_Holder>
{
public:
int operator()()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , false> value_type;
test::test_generic_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::auto_base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::auto_member_hook_type
, &value_type::auto_node_
>
>::type
, 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 ConstantTimeSize, typename HeaderHolder >
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< splaytree_defaults, Option1, Option2, Option3 >::type packed_options;
typedef typename packed_options::compare compare_option;
typedef boost::intrusive::splay_multiset< typename Value_Traits::value_type,
value_traits< Value_Traits >,
constant_time_size< ConstantTimeSize >,
compare< compare_option >,
header_holder_type< HeaderHolder >
> type;
};
};
template < bool ConstantTimeSize >
template < bool ConstantTimeSize, bool Map >
struct test_main_template_bptr
{
void operator () ()
{
typedef BPtr_Value value_type;
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< value_type > allocator_type;
static void execute()
{
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
allocator_type::init();
test::test_generic_multiset< value_traits,
Get_Preset_Container< value_traits, ConstantTimeSize,
bounded_pointer_holder< value_type > >::template GetContainer
>::test_all();
assert(allocator_type::is_clear());
allocator_type::destroy();
}
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_multiset
< value_traits
, rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
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 >()();
//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>::execute();
test_main_template<void*, false, false, true>::execute();
//test_main_template<void*, false, true, false>::execute();
test_main_template<void*, false, true, true>::execute();
//test_main_template<void*, true, false, false>::execute();
test_main_template<void*, true, false, true>::execute();
//test_main_template<void*, true, true, false>::execute();
test_main_template<void*, true, true, true>::execute();
//smart_ptr
test_main_template<smart_ptr<void>, false, false, false>::execute();
//test_main_template<smart_ptr<void>, false, false, true>::execute();
test_main_template<smart_ptr<void>, false, true, false>::execute();
//test_main_template<smart_ptr<void>, false, true, true>::execute();
test_main_template<smart_ptr<void>, true, false, false>::execute();
//test_main_template<smart_ptr<void>, true, false, true>::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();
}
+82 -234
View File
@@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013
// (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
@@ -13,260 +13,108 @@
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "bs_test_common.hpp"
#include "generic_set_test.hpp"
namespace boost { namespace intrusive { namespace test {
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct has_splay<boost::intrusive::splay_set<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = true;
};
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct has_rebalance<boost::intrusive::splay_set<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = true;
};
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct has_const_searches<boost::intrusive::splay_set<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = false;
};
}}}
using namespace boost::intrusive;
struct my_tag;
template<class VoidPointer>
struct hooks
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef bs_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
typedef bs_set_base_hook
< link_mode<auto_unlink>
, void_pointer<VoidPointer>
, tag<my_tag> > 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 >,
splaytree_algorithms
> nonhook_node_member_type;
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
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));
};
};
// container generator with void node allocator
template < bool Default_Holder >
struct GetContainer_With_Holder
{
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainer
{
typedef boost::intrusive::splay_set
< ValueType
, Option1
, Option2
, Option3
> type;
};
};
// 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< splaytree_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::splay_set
< ValueType
, Option1
, Option2
, Option3
, header_holder_type< pointer_holder< node > >
> type;
};
};
template<class VoidPointer, bool constant_time_size, bool Default_Holder>
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template
{
public:
int operator()()
static void execute()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , constant_time_size> value_type;
test::test_generic_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < nonhook_node_member_value_traits< value_type,
typename hooks<VoidPointer>::nonhook_node_member_type,
&value_type::nhn_member_,
safe_link
>,
GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
return 0;
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
< base_hook_t
, rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
//member
typedef typename testval_traits_t::member_value_traits member_hook_t;
test::test_generic_set
< member_hook_t
, rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
//nonmember
test::test_generic_set
< typename testval_traits_t::nonhook_value_traits
, rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool Default_Holder>
class test_main_template<VoidPointer, false, Default_Holder>
{
public:
int operator()()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , false> value_type;
test::test_generic_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::auto_base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::auto_member_hook_type
, &value_type::auto_node_
>
>::type
, 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 ConstantTimeSize, typename HeaderHolder >
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< splaytree_defaults, Option1, Option2, Option3 >::type packed_options;
typedef typename packed_options::compare compare_option;
typedef boost::intrusive::splay_set< typename Value_Traits::value_type,
value_traits< Value_Traits >,
constant_time_size< ConstantTimeSize >,
compare< compare_option >,
header_holder_type< HeaderHolder >
> type;
};
};
template < bool ConstantTimeSize >
template < bool ConstantTimeSize, bool Map >
struct test_main_template_bptr
{
void operator () ()
{
typedef BPtr_Value value_type;
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< value_type > allocator_type;
static void execute()
{
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
allocator_type::init();
test::test_generic_set< value_traits,
Get_Preset_Container< value_traits, ConstantTimeSize,
bounded_pointer_holder< value_type > >::template GetContainer
>::test_all();
assert(allocator_type::is_clear());
allocator_type::destroy();
}
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_set
< value_traits
, rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
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 >()();
//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>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false>::execute();
//test_main_template<void*, true, true, true>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true>::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();
}
+142 -60
View File
@@ -18,17 +18,15 @@
#include <boost/intrusive/detail/simple_disposers.hpp>
#include <boost/intrusive/detail/iterator.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/static_assert.hpp>
#include "iterator_test.hpp"
namespace boost {
namespace intrusive {
namespace test {
template<class T>
struct is_unordered
{
static const bool value = false;
};
BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(is_unordered, hasher)
template<class Container>
struct test_container_typedefs
@@ -174,42 +172,66 @@ 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::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());
for( typename Data::const_iterator di = d.begin(), de = d.end();
di != de; ++di )
{
BOOST_TEST( c.find(*di) != c.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(*da, c.hash_function(), c.key_eq());
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
( *da, c.hash_function(), c.key_eq(), detail::null_disposer() );
( key_of_value()(*da), c.hash_function(), c.key_eq(), detail::null_disposer() );
BOOST_TEST( second_erase == 0 );
BOOST_TEST( c.count(*da, c.hash_function(), c.key_eq()) == 0 );
BOOST_TEST( c.count(*db, c.hash_function(), c.key_eq()) != 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(*da, c.hash_function(), c.key_eq()) == c.end() );
BOOST_TEST( c.find(*db, c.hash_function(), c.key_eq()) != c.end() );
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(*db, c.hash_function(), c.key_eq()).first != 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(*da, c.hash_function(), c.key_eq()).first == c.end() );
BOOST_TEST( c.equal_range(key_of_value()(*da), c.hash_function(), c.key_eq()).first == c.end() );
//
//suggested_upper_bucket_count
@@ -243,7 +265,10 @@ 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::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 );
@@ -255,37 +280,61 @@ void test_common_unordered_and_associative_container(Container & c, Data & d, bo
c.clear();
c.insert(d.begin(), d.end());
for( typename Data::const_iterator di = d.begin(), de = d.end();
di != de; ++di )
{
BOOST_TEST( c.find(*di, c.key_comp()) != c.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(*da, c.key_comp());
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( *da, c.key_comp(), detail::null_disposer() );
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(*da, c.key_comp()) == 0 );
BOOST_TEST( c.count(*db, c.key_comp()) != 0 );
BOOST_TEST( c.find(*da, c.key_comp()) == c.end() );
BOOST_TEST( c.find(*db, c.key_comp()) != c.end() );
BOOST_TEST( c.equal_range(*db, c.key_comp()).first != c.end() );
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(*da, c.key_comp()).first == c.end() );
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::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 );
@@ -298,31 +347,51 @@ void test_common_unordered_and_associative_container(Container & c, Data & d)
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( c.find(*di) != c.end() );
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(*da);
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( *da, detail::null_disposer() );
size_type second_erase = c.erase_and_dispose( key_of_value()(*da), detail::null_disposer() );
BOOST_TEST( second_erase == 0 );
BOOST_TEST( c.count(*da) == 0 );
BOOST_TEST( c.count(*db) != 0 );
BOOST_TEST( c.count(key_of_value()(*da)) == 0 );
BOOST_TEST( c.count(key_of_value()(*db)) != 0 );
BOOST_TEST( c.find(*da) == c.end() );
BOOST_TEST( c.find(*db) != c.end() );
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(*db).first != c.end() );
BOOST_TEST( c.equal_range(*da).first == c.equal_range(*da).second );
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();
@@ -333,12 +402,12 @@ void test_common_unordered_and_associative_container(Container & c, Data & d)
BOOST_TEST( c.empty());
for( typename Data::const_iterator di = d.begin(), de = d.end();
di != de; ++di )
{ BOOST_TEST( move_c.find(*di) != move_c.end() ); }
{ 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(*di) != c.end() ); }
{ BOOST_TEST( c.find(key_of_value()(*di)) != c.end() ); }
BOOST_TEST( move_c.empty());
}
typedef detail::bool_<is_unordered<Container>::value> enabler;
@@ -348,25 +417,29 @@ void test_common_unordered_and_associative_container(Container & c, Data & d)
template< class Container, class Data >
void test_associative_container_invariants(Container & c, Data & d)
{
typedef typename Container::const_iterator const_iterator;
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(*di);
const_iterator ci = c.find(key_of_value()(*di));
BOOST_TEST( ci != c.end() );
BOOST_TEST( ! c.value_comp()(*ci, *di) );
const_iterator cil = c.lower_bound(*di);
const_iterator ciu = c.upper_bound(*di);
std::pair<const_iterator, const_iterator> er = c.equal_range(*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(*di) > 1){
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)) );
}
}
}
@@ -390,29 +463,30 @@ void test_associative_container(Container & c, Data & 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::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(*di);
size_type nb = c.bucket(*i);
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(*di)) == &*i );
BOOST_TEST( &*c.local_iterator_to(*const_cast<const Container &>(c).find(*di)) == &*i );
BOOST_TEST( &*Container::s_local_iterator_to(*c.find(*di)) == &*i );
BOOST_TEST( &*Container::s_local_iterator_to(*const_cast<const Container &>(c).find(*di)) == &*i );
std::pair<const_iterator, const_iterator> er = c.equal_range(*di);
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(*di));
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()(*i, *n) );
BOOST_TEST( c.hash_function()(*i) == c.hash_function()(*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))) );
}
}
}
@@ -470,6 +544,14 @@ void test_non_unique_container(Container & c, Data & d)
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); }
}}}
#endif //#ifndef BOOST_INTRUSIVE_TEST_CONTAINER_HPP
+36
View File
@@ -13,8 +13,25 @@
#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)
@@ -39,6 +56,25 @@ bool test_equal(It1 f1, It1 l1, It2 f2)
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{
+83 -202
View File
@@ -1,7 +1,6 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2013.
// (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
@@ -10,230 +9,112 @@
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/treap_set.hpp>
#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"
namespace boost { namespace intrusive { namespace test {
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct has_insert_before<boost::intrusive::treap_multiset<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = true;
};
}}}
using namespace boost::intrusive;
struct my_tag;
template<class VoidPointer>
struct hooks
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef bs_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
typedef bs_set_base_hook
< void_pointer<VoidPointer>
, tag<my_tag> > auto_base_hook_type;
typedef bs_set_member_hook
< void_pointer<VoidPointer> > member_hook_type;
typedef bs_set_member_hook
< void_pointer<VoidPointer> > auto_member_hook_type;
typedef nonhook_node_member< tree_node_traits< VoidPointer >,
treap_algorithms
> nonhook_node_member_type;
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
template < class Option1 =void
, class Option2 =void
>
struct container
{
typedef sg_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));
};
};
// container generator with void node allocator
template < bool Default_Holder >
struct GetContainer_With_Holder
{
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainer
{
typedef boost::intrusive::treap_multiset
< ValueType
, Option1
, Option2
, Option3
> type;
};
};
// 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< treap_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::treap_multiset
< ValueType
, Option1
, Option2
, Option3
, header_holder_type< pointer_holder< node > >
> type;
};
};
template<class VoidPointer, bool constant_time_size, bool Default_Holder>
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template
{
public:
int operator()()
static void execute()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , constant_time_size> value_type;
test::test_generic_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < nonhook_node_member_value_traits< value_type,
typename hooks<VoidPointer>::nonhook_node_member_type,
&value_type::nhn_member_,
safe_link
>,
GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
return 0;
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
< base_hook_t
, rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
//member
typedef typename testval_traits_t::member_value_traits member_hook_t;
test::test_generic_multiset
< member_hook_t
, rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
//nonmember
test::test_generic_multiset
< typename testval_traits_t::nonhook_value_traits
, rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool Default_Holder>
class test_main_template<VoidPointer, false, Default_Holder>
{
public:
int operator()()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , false> value_type;
test::test_generic_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::auto_base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::auto_member_hook_type
, &value_type::auto_node_
>
>::type
, 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 ConstantTimeSize, typename HeaderHolder >
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< treap_defaults, Option1, Option2, Option3 >::type packed_options;
typedef typename packed_options::compare compare_option;
typedef boost::intrusive::treap_multiset< typename Value_Traits::value_type,
value_traits< Value_Traits >,
constant_time_size< ConstantTimeSize >,
compare< compare_option >,
header_holder_type< HeaderHolder >
> type;
};
};
template < bool ConstantTimeSize >
template < bool ConstantTimeSize, bool Map >
struct test_main_template_bptr
{
void operator () ()
{
typedef BPtr_Value value_type;
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< value_type > allocator_type;
static void execute()
{
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
allocator_type::init();
test::test_generic_multiset< value_traits,
Get_Preset_Container< value_traits, ConstantTimeSize,
bounded_pointer_holder< value_type > >::template GetContainer
>::test_all();
assert(allocator_type::is_clear());
allocator_type::destroy();
}
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_multiset
< value_traits
, rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
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 >()();
//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>::execute();
test_main_template<void*, false, false, true>::execute();
//test_main_template<void*, false, true, false>::execute();
test_main_template<void*, false, true, true>::execute();
//test_main_template<void*, true, false, false>::execute();
test_main_template<void*, true, false, true>::execute();
//test_main_template<void*, true, true, false>::execute();
test_main_template<void*, true, true, true>::execute();
//smart_ptr
test_main_template<smart_ptr<void>, false, false, false>::execute();
//test_main_template<smart_ptr<void>, false, false, true>::execute();
test_main_template<smart_ptr<void>, false, true, false>::execute();
//test_main_template<smart_ptr<void>, false, true, true>::execute();
test_main_template<smart_ptr<void>, true, false, false>::execute();
//test_main_template<smart_ptr<void>, true, false, true>::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();
}
+83 -219
View File
@@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2013.
// (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
@@ -9,248 +9,112 @@
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/treap_set.hpp>
#include "itestvalue.hpp"
#include <boost/intrusive/treap_set.hpp>
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "bs_test_common.hpp"
#include "generic_set_test.hpp"
namespace boost { namespace intrusive { namespace test {
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct has_insert_before<boost::intrusive::treap_set<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = true;
};
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
struct is_treap<boost::intrusive::treap_set<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
> >
{
static const bool value = true;
};
}}}
using namespace boost::intrusive;
struct my_tag;
template<class VoidPointer>
struct hooks
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef bs_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
typedef bs_set_base_hook
< void_pointer<VoidPointer>
, tag<my_tag> > auto_base_hook_type;
typedef bs_set_member_hook
< void_pointer<VoidPointer> > member_hook_type;
typedef bs_set_member_hook
< void_pointer<VoidPointer> > auto_member_hook_type;
typedef nonhook_node_member< tree_node_traits< VoidPointer >,
treap_algorithms
> nonhook_node_member_type;
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
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
, Option1
, Option2
> type;
BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value));
};
};
// container generator with void node allocator
template < bool Default_Holder >
struct GetContainer_With_Holder
{
template< class ValueType
, class Option1 =void
, class Option2 =void
, class Option3 =void
>
struct GetContainer
{
typedef boost::intrusive::treap_set
< ValueType
, Option1
, Option2
, Option3
> type;
};
};
// 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< treap_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::treap_set
< ValueType
, Option1
, Option2
, Option3
, header_holder_type< pointer_holder< node > >
> type;
};
};
template<class VoidPointer, bool constant_time_size, bool Default_Holder>
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template
{
public:
int operator()()
static void execute()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , constant_time_size> value_type;
test::test_generic_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < nonhook_node_member_value_traits< value_type,
typename hooks<VoidPointer>::nonhook_node_member_type,
&value_type::nhn_member_,
safe_link
>,
GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
return 0;
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
< base_hook_t
, rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
//member
typedef typename testval_traits_t::member_value_traits member_hook_t;
test::test_generic_set
< member_hook_t
, rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
//nonmember
test::test_generic_set
< typename testval_traits_t::nonhook_value_traits
, rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool Default_Holder>
class test_main_template<VoidPointer, false, Default_Holder>
{
public:
int operator()()
{
using namespace boost::intrusive;
typedef testvalue<hooks<VoidPointer> , false> value_type;
test::test_generic_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::auto_base_hook_type
>::type
, GetContainer_With_Holder< Default_Holder >::template GetContainer
>::test_all();
test::test_generic_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::auto_member_hook_type
, &value_type::auto_node_
>
>::type
, 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 ConstantTimeSize, typename HeaderHolder >
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< treap_defaults, Option1, Option2, Option3 >::type packed_options;
typedef typename packed_options::compare compare_option;
typedef boost::intrusive::treap_set< typename Value_Traits::value_type,
value_traits< Value_Traits >,
constant_time_size< ConstantTimeSize >,
compare< compare_option >,
header_holder_type< HeaderHolder >
> type;
};
};
template < bool ConstantTimeSize >
template < bool ConstantTimeSize, bool Map >
struct test_main_template_bptr
{
void operator () ()
{
typedef BPtr_Value value_type;
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< value_type > allocator_type;
static void execute()
{
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
allocator_type::init();
test::test_generic_set< value_traits,
Get_Preset_Container< value_traits, ConstantTimeSize,
bounded_pointer_holder< value_type > >::template GetContainer
>::test_all();
assert(allocator_type::is_clear());
allocator_type::destroy();
}
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_set
< value_traits
, rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
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 >()();
//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>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false>::execute();
//test_main_template<void*, true, true, true>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true>::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();
}
+77 -838
View File
@@ -1,7 +1,6 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2013.
// (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
@@ -23,861 +22,101 @@
#include "test_macros.hpp"
#include "test_container.hpp"
namespace boost { namespace intrusive { namespace test {
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5, class O6>
#else
template<class T, class ...Options>
#endif
struct is_unordered<boost::intrusive::unordered_multiset<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5, O6
#else
Options...
#endif
> >
{
static const bool value = true;
};
}}}
#include "unordered_test_common.hpp"
#include "unordered_test.hpp"
using namespace boost::intrusive;
struct my_tag;
template<class VoidPointer>
struct hooks
template < class ValueTraits, bool ConstantTimeSize, bool CacheBegin, bool CompareHash, bool Incremental, bool Map, bool DefaultHolder >
struct rebinder
{
typedef unordered_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
typedef unordered_set_base_hook
< link_mode<auto_unlink>
, void_pointer<VoidPointer>
, tag<my_tag>
, store_hash<true>
> auto_base_hook_type;
typedef unordered_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
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 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));
};
};
static const std::size_t BucketSize = 8;
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
struct test_unordered_multiset
{
typedef typename ValueTraits::value_type value_type;
static void test_all (std::vector<value_type>& values);
static void test_sort(std::vector<value_type>& values);
static void test_insert(std::vector<value_type>& values);
static void test_swap(std::vector<value_type>& values);
static void test_rehash(std::vector<value_type>& values, detail::true_);
static void test_rehash(std::vector<value_type>& values, detail::false_);
static void test_find(std::vector<value_type>& values);
static void test_impl();
static void test_clone(std::vector<value_type>& values);
};
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_all (std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
{
typename unordered_multiset_type::bucket_type buckets [BucketSize];
unordered_multiset_type testset
(bucket_traits(pointer_traits<typename unordered_multiset_type::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());
test::test_non_unique_container(testset, values);
}
{
std::vector<typename ValueTraits::value_type> values(BucketSize);
for (int i = 0; i < (int)BucketSize; ++i)
(&values[i])->value_ = i;
typename unordered_multiset_type::bucket_type buckets [BucketSize];
unordered_multiset_type testset(bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets[0]), BucketSize));
testset.insert(values.begin(), values.end());
test::test_iterator_forward(testset);
}
test_sort(values);
test_insert(values);
test_swap(values);
test_rehash(values, detail::bool_<Incremental>());
test_find(values);
test_impl();
test_clone(values);
}
//test case due to an error in tree implementation:
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
::test_impl()
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
std::vector<value_type> values (5);
for (int i = 0; i < 5; ++i)
values[i].value_ = i;
typename unordered_multiset_type::bucket_type buckets [BucketSize];
unordered_multiset_type testset(bucket_traits(
pointer_traits<typename unordered_multiset_type::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 ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
::test_sort(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
typename unordered_multiset_type::bucket_type buckets [BucketSize];
unordered_multiset_type testset1
(values.begin(), values.end(), bucket_traits
(pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets[0]), BucketSize));
if(Incremental){
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
else{
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
testset1.clear();
BOOST_TEST (testset1.empty());
}
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
::test_insert(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
typedef typename unordered_multiset_type::iterator iterator;
{
typename unordered_multiset_type::bucket_type buckets [BucketSize];
unordered_multiset_type testset(bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets[0]), BucketSize));
testset.insert(&values[0] + 2, &values[0] + 5);
const unordered_multiset_type& const_testset = testset;
if(Incremental){
{
{ int init_values [] = { 4, 5, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
typename unordered_multiset_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( init_values, const_testset.begin() ); }
testset.clear();
testset.insert(&values[0], &values[0] + values.size());
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
BOOST_TEST (testset.erase(1) == 1);
BOOST_TEST (testset.erase(2) == 2);
BOOST_TEST (testset.erase(3) == 1);
BOOST_TEST (testset.erase(4) == 1);
BOOST_TEST (testset.erase(5) == 1);
BOOST_TEST (testset.empty() == true);
//Now with a single bucket
typename unordered_multiset_type::bucket_type single_bucket[1];
unordered_multiset_type testset2(bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(single_bucket[0]), 1));
testset2.insert(&values[0], &values[0] + values.size());
BOOST_TEST (testset2.erase(5) == 1);
BOOST_TEST (testset2.erase(2) == 2);
BOOST_TEST (testset2.erase(1) == 1);
BOOST_TEST (testset2.erase(4) == 1);
BOOST_TEST (testset2.erase(3) == 1);
BOOST_TEST (testset2.empty() == true);
}
}
else{
{
{ int init_values [] = { 1, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
typename unordered_multiset_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( init_values, const_testset.begin() ); }
testset.clear();
testset.insert(&values[0], &values[0] + values.size());
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
BOOST_TEST (testset.erase(1) == 1);
BOOST_TEST (testset.erase(2) == 2);
BOOST_TEST (testset.erase(3) == 1);
BOOST_TEST (testset.erase(4) == 1);
BOOST_TEST (testset.erase(5) == 1);
BOOST_TEST (testset.empty() == true);
//Now with a single bucket
typename unordered_multiset_type::bucket_type single_bucket[1];
unordered_multiset_type testset2(bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(single_bucket[0]), 1));
testset2.insert(&values[0], &values[0] + values.size());
BOOST_TEST (testset2.erase(5) == 1);
BOOST_TEST (testset2.erase(2) == 2);
BOOST_TEST (testset2.erase(1) == 1);
BOOST_TEST (testset2.erase(4) == 1);
BOOST_TEST (testset2.erase(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_multiset_type::bucket_type single_bucket[1];
for(unsigned int i = 0, max = random_size; i != max; ++i){
std::vector<typename ValueTraits::value_type> data (random_size);
for (unsigned int j = 0; j < random_size; ++j)
data[j].value_ = random_init[j];
unordered_multiset_type testset_new(bucket_traits(
pointer_traits<typename unordered_multiset_type::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));
}
}
}
{
typename unordered_multiset_type::bucket_type buckets [BucketSize];
const unsigned int NumBucketSize = BucketSize;
const unsigned int LoadFactor = 3;
const unsigned int NumIterations = NumBucketSize*LoadFactor;
std::vector<value_type> random_init(NumIterations);//Preserve memory
std::vector<value_type> set_tester;
set_tester.reserve(NumIterations);
//Initialize values
for (unsigned int i = 0; i < NumIterations; ++i){
random_init[i].value_ = i*2;//(i/LoadFactor)*LoadFactor;
}
for(unsigned int initial_pos = 0; initial_pos != (NumIterations+1); ++initial_pos){
for(unsigned int final_pos = initial_pos; final_pos != (NumIterations+1); ++final_pos){
//Create intrusive container inserting values
unordered_multiset_type testset
( &random_init[0]
, &random_init[0] + random_init.size()
, bucket_traits(pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets[0]), NumBucketSize));
BOOST_TEST (testset.size() == random_init.size());
//Obtain the iterator range to erase
iterator it_beg_pos = testset.begin();
for(unsigned int it_beg_pos_num = 0; it_beg_pos_num != initial_pos; ++it_beg_pos_num){
++it_beg_pos;
}
iterator it_end_pos(it_beg_pos);
for(unsigned int it_end_pos_num = 0; it_end_pos_num != (final_pos - initial_pos); ++it_end_pos_num){
++it_end_pos;
}
//Erase the same values in both the intrusive and original vector
std::size_t erased_cnt = boost::intrusive::iterator_distance(it_beg_pos, it_end_pos);
//Erase values from the intrusive container
testset.erase(it_beg_pos, it_end_pos);
BOOST_TEST (testset.size() == (random_init.size()-(final_pos - initial_pos)));
//Now test...
BOOST_TEST ((random_init.size() - erased_cnt) == testset.size());
//Create an ordered copy of the intrusive container
set_tester.insert(set_tester.end(), testset.begin(), testset.end());
std::sort(set_tester.begin(), set_tester.end());
{
typename std::vector<value_type>::iterator it = set_tester.begin(), itend = set_tester.end();
typename std::vector<value_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 ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_swap(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
typename unordered_multiset_type::bucket_type buckets [BucketSize];
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
unordered_multiset_type testset1(&values[0], &values[0] + 2,
bucket_traits(pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets[0]), BucketSize));
unordered_multiset_type testset2(bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets2[0]), BucketSize));
testset2.insert (&values[0] + 2, &values[0] + 6);
testset1.swap (testset2);
if(Incremental){
{ int init_values [] = { 4, 5, 1, 2 };
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[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( 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]);
}
}
//test: rehash:
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
::test_rehash(std::vector<typename ValueTraits::value_type>& values, detail::true_)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
//Build a uset
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
typename unordered_multiset_type::bucket_type buckets2 [BucketSize*2];
unordered_multiset_type testset1(&values[0], &values[0] + values.size(),
bucket_traits(pointer_traits<typename unordered_multiset_type::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( init_values, testset1.begin() ); }
//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( init_values, testset1.begin() ); }
//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( init_values, testset1.begin() ); }
}
//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( init_values, testset1.begin() ); }
//
//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<typename unordered_multiset_type::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( init_values, testset1.begin() ); }
//
//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<typename unordered_multiset_type::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( init_values, testset1.begin() ); }
//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<typename unordered_multiset_type::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( init_values, testset1.begin() ); }
//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<typename unordered_multiset_type::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( init_values, testset1.begin() ); }
//Full shrink rehash
testset1.rehash(bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets1[0]), 4));
BOOST_TEST (testset1.size() == values.size());
BOOST_TEST (testset1.incremental_rehash() == false);
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Full shrink rehash again
testset1.rehash(bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets1[0]), 2));
BOOST_TEST (testset1.size() == values.size());
BOOST_TEST (testset1.incremental_rehash() == false);
{ int init_values [] = { 2, 2, 4, 3, 5, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Full growing rehash
testset1.rehash(bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets1[0]), BucketSize));
BOOST_TEST (testset1.size() == values.size());
BOOST_TEST (testset1.incremental_rehash() == false);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//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( init_values, testset1.begin() ); }
}
//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( init_values, testset1.begin() ); }
//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( init_values, testset1.begin() ); }
//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( init_values, testset1.begin() ); }
}
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
::test_rehash(std::vector<typename ValueTraits::value_type>& values, detail::false_)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
typename unordered_multiset_type::bucket_type buckets2 [2];
typename unordered_multiset_type::bucket_type buckets3 [BucketSize*2];
unordered_multiset_type testset1(&values[0], &values[0] + 6, bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets1[0]), BucketSize));
BOOST_TEST (testset1.size() == values.size());
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
testset1.rehash(bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets2[0]), 2));
BOOST_TEST (testset1.size() == values.size());
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
testset1.rehash(bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets3[0]), BucketSize*2));
BOOST_TEST (testset1.size() == values.size());
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Now rehash reducing the buckets
testset1.rehash(bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets3[0]), 2));
BOOST_TEST (testset1.size() == values.size());
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Now rehash increasing the buckets
testset1.rehash(bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets3[0]), BucketSize*2));
BOOST_TEST (testset1.size() == values.size());
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
//test: find, equal_range (lower_bound, upper_bound):
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_find(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
typename unordered_multiset_type::bucket_type buckets[BucketSize];
unordered_multiset_type testset(values.begin(), values.end(), bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets[0]), BucketSize));
typedef typename unordered_multiset_type::iterator iterator;
value_type cmp_val;
cmp_val.value_ = 2;
iterator i = testset.find (cmp_val);
BOOST_TEST (i->value_ == 2);
BOOST_TEST ((++i)->value_ == 2);
std::pair<iterator,iterator> range = testset.equal_range (cmp_val);
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 (cmp_val) == testset.end());
}
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
::test_clone(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
{
//Test with equal bucket arrays
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets1[0]), BucketSize));
unordered_multiset_type testset2 (bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets2[0]), BucketSize));
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
//Ordering is not guarantee in the cloning so insert data in a set and test
std::multiset<typename ValueTraits::value_type>
src(testset1.begin(), testset1.end());
std::multiset<typename ValueTraits::value_type>
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());
}
{
//Test with bigger source bucket arrays
typename unordered_multiset_type::bucket_type buckets1 [BucketSize*2];
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets1[0]), BucketSize*2));
unordered_multiset_type testset2 (bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets2[0]), BucketSize));
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
//Ordering is not guarantee in the cloning so insert data in a set and test
std::multiset<typename ValueTraits::value_type>
src(testset1.begin(), testset1.end());
std::multiset<typename ValueTraits::value_type>
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());
}
{
//Test with smaller source bucket arrays
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
typename unordered_multiset_type::bucket_type buckets2 [BucketSize*2];
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets1[0]), BucketSize));
unordered_multiset_type testset2 (bucket_traits(
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
pointer_to(buckets2[0]), BucketSize*2));
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
//Ordering is not guaranteed in the cloning so insert data in a set and test
std::multiset<typename ValueTraits::value_type>
src(testset1.begin(), testset1.end());
std::multiset<typename ValueTraits::value_type>
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());
}
}
template<class VoidPointer, bool constant_time_size, bool Incremental>
template<class VoidPointer, bool ConstantTimeSize, bool Map, bool DefaultHolder>
class test_main_template
{
public:
int operator()()
static void execute()
{
typedef testvalue<hooks<VoidPointer> , constant_time_size> value_type;
typedef testvalue<unordered_hooks<VoidPointer> > value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
std::vector<testvalue<hooks<VoidPointer> , constant_time_size> > data (6);
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];
test_unordered_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, true
, false
, Incremental
>::test_all(data);
test_unordered_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, false
, false
, Incremental
>::test_all(data);
test_unordered_multiset < nonhook_node_member_value_traits< value_type,
typename hooks<VoidPointer>::nonhook_node_member_type,
&value_type::nhn_member_,
safe_link
>,
false,
false,
Incremental
>::test_all(data);
return 0;
}
};
template<class VoidPointer, bool Incremental>
class test_main_template<VoidPointer, false, Incremental>
{
public:
int operator()()
{
typedef testvalue<hooks<VoidPointer> , false> value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
std::vector<testvalue<hooks<VoidPointer> , false> > data (6);
for (int i = 0; i < 6; ++i)
data[i].value_ = random_init[i];
test_unordered_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, false
, false
, Incremental
>::test_all(data);
test_unordered_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, true
, false
, Incremental
>::test_all(data);
test_unordered_multiset < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::auto_base_hook_type
>::type
, false
, false
, Incremental
>::test_all(data);
test_unordered_multiset < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::auto_member_hook_type
, &value_type::auto_node_
>
>::type
, false
, true
, Incremental
>::test_all(data);
return 0;
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
< base_hook_t //cache_begin, compare_hash, incremental
, rebinder<base_hook_t, ConstantTimeSize, ConstantTimeSize, !ConstantTimeSize, !!ConstantTimeSize, Map, DefaultHolder>
>::test_all(data);
//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
< member_hook_t //cache_begin, compare_hash, incremental
, rebinder<member_hook_t, ConstantTimeSize, false, !ConstantTimeSize, false, !ConstantTimeSize, DefaultHolder>
>::test_all(data);
//nonmember
test::test_unordered
< typename testval_traits_t::nonhook_value_traits //cache_begin, compare_hash, incremental
, rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, false, false, false, Map, DefaultHolder>
>::test_all(data);
}
};
int main()
{
test_main_template<void*, false, true>()();
test_main_template<smart_ptr<void>, false, true>()();
test_main_template<void*, true, true>()();
test_main_template<smart_ptr<void>, true, true>()();
test_main_template<void*, false, false>()();
test_main_template<smart_ptr<void>, false, false>()();
test_main_template<void*, true, true>()();
test_main_template<smart_ptr<void>, true, false>()();
//VoidPointer x ConstantTimeSize x Map x DefaultHolder
//void pointer
test_main_template<void*, false, false, false>::execute();
test_main_template<void*, false, true, false>::execute();
test_main_template<void*, true, false, false>::execute();
test_main_template<void*, true, true, false>::execute();
//smart_ptr
test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, true, false>::execute();
/*
//bounded_ptr (bool ConstantTimeSize, bool Map)
test_main_template_bptr< false, false >::execute();
//test_main_template_bptr< false, true >::execute();
//test_main_template_bptr< true, false >::execute();
test_main_template_bptr< true, true >::execute();
*/
return boost::report_errors();
}
+77 -692
View File
@@ -1,7 +1,6 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2013.
// (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
@@ -21,715 +20,101 @@
#include <boost/detail/lightweight_test.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
namespace boost { namespace intrusive { namespace test {
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5, class O6>
#else
template<class T, class ...Options>
#endif
struct is_unordered<boost::intrusive::unordered_set<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5, O6
#else
Options...
#endif
> >
{
static const bool value = true;
};
}}}
#include "unordered_test_common.hpp"
#include "unordered_test.hpp"
using namespace boost::intrusive;
struct my_tag;
template<class VoidPointer>
struct hooks
template < class ValueTraits, bool ConstantTimeSize, bool CacheBegin, bool CompareHash, bool Incremental, bool Map, bool DefaultHolder >
struct rebinder
{
typedef unordered_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
typedef unordered_set_base_hook
< link_mode<auto_unlink>
, void_pointer<VoidPointer>
, tag<my_tag>
, store_hash<true>
> auto_base_hook_type;
typedef unordered_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
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 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
, 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));
};
};
static const std::size_t BucketSize = 8;
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
struct test_unordered_set
{
typedef typename ValueTraits::value_type value_type;
static void test_all(std::vector<value_type>& values);
static void test_sort(std::vector<value_type>& values);
static void test_insert(std::vector<value_type>& values);
static void test_swap(std::vector<value_type>& values);
static void test_rehash(std::vector<value_type>& values, detail::true_);
static void test_rehash(std::vector<value_type>& values, detail::false_);
static void test_find(std::vector<value_type>& values);
static void test_impl();
static void test_clone(std::vector<value_type>& values);
};
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_all(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
{
typename unordered_set_type::bucket_type buckets [BucketSize];
unordered_set_type testset(bucket_traits(
pointer_traits<typename unordered_set_type::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());
test::test_unique_container(testset, values);
}
{
std::vector<typename ValueTraits::value_type> values(BucketSize);
for (int i = 0; i < (int)BucketSize; ++i)
(&values[i])->value_ = i;
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.begin(), values.end());
test::test_iterator_forward(testset);
}
test_sort(values);
test_insert(values);
test_swap(values);
test_rehash(values, detail::bool_<Incremental>());
test_find(values);
test_impl();
test_clone(values);
}
//test case due to an error in tree implementation:
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::test_impl()
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
std::vector<value_type> values (5);
for (int i = 0; i < 5; ++i)
values[i].value_ = i;
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));
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 ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_sort(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
typename unordered_set_type::bucket_type buckets [BucketSize];
unordered_set_type testset1(values.begin(), values.end(), bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets[0]), BucketSize));
BOOST_TEST (5 == boost::intrusive::iterator_distance(testset1.begin(), testset1.end()));
if(Incremental){
{ int init_values [] = { 4, 5, 1, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
else{
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
testset1.clear();
BOOST_TEST (testset1.empty());
}
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_insert(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
typename unordered_set_type::bucket_type buckets [BucketSize];
unordered_set_type testset(bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets[0]), BucketSize));
testset.insert(&values[0] + 2, &values[0] + 5);
const unordered_set_type& const_testset = testset;
if(Incremental)
{
{ int init_values [] = { 4, 5, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
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( init_values, const_testset.begin() ); }
}
else{
{ int init_values [] = { 1, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
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( init_values, const_testset.begin() ); }
}
}
//test: insert (seq-version), swap, erase (seq-version), size:
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_swap(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
typename unordered_set_type::bucket_type buckets1 [BucketSize];
typename unordered_set_type::bucket_type buckets2 [BucketSize];
unordered_set_type testset1(&values[0], &values[0] + 2, bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets1[0]), BucketSize));
unordered_set_type testset2(bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets2[0]), BucketSize));
testset2.insert (&values[0] + 2, &values[0] + 6);
testset1.swap (testset2);
if(Incremental){
{ int init_values [] = { 4, 5, 1, 2 };
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[4]), testset1.end());
BOOST_TEST (testset1.size() == 1);
BOOST_TEST (&*testset1.begin() == &values[2]);
}
else{
{ 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]);
}
}
//test: rehash:
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_rehash(std::vector<typename ValueTraits::value_type>& values, detail::true_)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
//Build a uset
typename unordered_set_type::bucket_type buckets1 [BucketSize];
typename unordered_set_type::bucket_type buckets2 [BucketSize*2];
unordered_set_type testset1(&values[0], &values[0] + 6, bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets1[0]), BucketSize));
//Test current state
BOOST_TEST(testset1.split_count() == BucketSize/2);
{ int init_values [] = { 4, 5, 1, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Incremental rehash step
BOOST_TEST (testset1.incremental_rehash() == true);
BOOST_TEST(testset1.split_count() == (BucketSize/2+1));
{ int init_values [] = { 5, 1, 2, 3, 4 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//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, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
//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, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//
//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<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets1[0]), BucketSize)) == false);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//
//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<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets2[0]), BucketSize)) == false);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//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<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets2[0]), BucketSize*2)) == true);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//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<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets1[0]), BucketSize)) == true);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Full shrink rehash
testset1.rehash(bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets1[0]), 4));
BOOST_TEST (testset1.size() == values.size()-1);
BOOST_TEST (testset1.incremental_rehash() == false);
{ int init_values [] = { 4, 5, 1, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Full shrink rehash again
testset1.rehash(bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets1[0]), 2));
BOOST_TEST (testset1.size() == values.size()-1);
BOOST_TEST (testset1.incremental_rehash() == false);
{ int init_values [] = { 2, 4, 3, 5, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Full growing rehash
testset1.rehash(bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets1[0]), BucketSize));
BOOST_TEST (testset1.size() == values.size()-1);
BOOST_TEST (testset1.incremental_rehash() == false);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//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, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
//Incremental rehash step
BOOST_TEST (testset1.incremental_rehash(false) == true);
BOOST_TEST(testset1.split_count() == (BucketSize/2+1));
{ int init_values [] = { 5, 1, 2, 3, 4 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//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, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//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, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
//test: rehash:
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_rehash(std::vector<typename ValueTraits::value_type>& values, detail::false_)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
typename unordered_set_type::bucket_type buckets1 [BucketSize];
typename unordered_set_type::bucket_type buckets2 [2];
typename unordered_set_type::bucket_type buckets3 [BucketSize*2];
unordered_set_type testset1(&values[0], &values[0] + 6, bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets1[0]), BucketSize));
BOOST_TEST (testset1.size() == values.size()-1);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
testset1.rehash(bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets2[0]), 2));
BOOST_TEST (testset1.size() == values.size()-1);
{ int init_values [] = { 4, 2, 5, 3, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
testset1.rehash(bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets3[0]), BucketSize*2));
BOOST_TEST (testset1.size() == values.size()-1);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Now rehash reducing the buckets
testset1.rehash(bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets3[0]), 2));
BOOST_TEST (testset1.size() == values.size()-1);
{ int init_values [] = { 4, 2, 5, 3, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Now rehash increasing the buckets
testset1.rehash(bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets3[0]), BucketSize*2));
BOOST_TEST (testset1.size() == values.size()-1);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
//test: find, equal_range (lower_bound, upper_bound):
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_find(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
typename unordered_set_type::bucket_type buckets [BucketSize];
unordered_set_type testset (values.begin(), values.end(), bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets[0]), BucketSize));
typedef typename unordered_set_type::iterator iterator;
value_type cmp_val;
cmp_val.value_ = 2;
iterator i = testset.find (cmp_val);
BOOST_TEST (i->value_ == 2);
BOOST_TEST ((++i)->value_ != 2);
std::pair<iterator,iterator> range = testset.equal_range (cmp_val);
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 (cmp_val) == testset.end());
}
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>
::test_clone(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
{
//Test with equal bucket arrays
typename unordered_set_type::bucket_type buckets1 [BucketSize];
typename unordered_set_type::bucket_type buckets2 [BucketSize];
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets1[0]), BucketSize));
unordered_set_type testset2 (bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets2[0]), BucketSize));
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
//Ordering is not guarantee in the cloning so insert data in a set and test
std::set<typename ValueTraits::value_type>
src(testset1.begin(), testset1.end());
std::set<typename ValueTraits::value_type>
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());
}
{
//Test with bigger source bucket arrays
typename unordered_set_type::bucket_type buckets1 [BucketSize*2];
typename unordered_set_type::bucket_type buckets2 [BucketSize];
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets1[0]), BucketSize*2));
unordered_set_type testset2 (bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets2[0]), BucketSize));
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
//Ordering is not guaranteed in the cloning so insert data in a set and test
std::set<typename ValueTraits::value_type>
src(testset1.begin(), testset1.end());
std::set<typename ValueTraits::value_type>
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());
}
{
//Test with smaller source bucket arrays
typename unordered_set_type::bucket_type buckets1 [BucketSize];
typename unordered_set_type::bucket_type buckets2 [BucketSize*2];
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets1[0]), BucketSize));
unordered_set_type testset2 (bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets2[0]), BucketSize*2));
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
//Ordering is not guarantee in the cloning so insert data in a set and test
std::set<typename ValueTraits::value_type>
src(testset1.begin(), testset1.end());
std::set<typename ValueTraits::value_type>
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());
}
}
template<class VoidPointer, bool constant_time_size, bool incremental>
template<class VoidPointer, bool ConstantTimeSize, bool Map, bool DefaultHolder>
class test_main_template
{
public:
int operator()()
static void execute()
{
typedef testvalue<hooks<VoidPointer> , constant_time_size> value_type;
typedef testvalue<unordered_hooks<VoidPointer> > value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
std::vector<testvalue<hooks<VoidPointer> , constant_time_size> > data (6);
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];
test_unordered_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, true
, false
, incremental
>::test_all(data);
test_unordered_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, false
, false
, incremental
>::test_all(data);
test_unordered_set < nonhook_node_member_value_traits< value_type,
typename hooks<VoidPointer>::nonhook_node_member_type,
&value_type::nhn_member_,
safe_link
>,
false,
false,
incremental
>::test_all(data);
return 0;
}
};
template<class VoidPointer, bool incremental>
class test_main_template<VoidPointer, false, incremental>
{
public:
int operator()()
{
typedef testvalue<hooks<VoidPointer> , false> value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
std::vector<testvalue<hooks<VoidPointer> , false> > data (6);
for (int i = 0; i < 6; ++i)
data[i].value_ = random_init[i];
test_unordered_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, true
, false
, incremental
>::test_all(data);
test_unordered_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, false
, false
, incremental
>::test_all(data);
test_unordered_set < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::auto_base_hook_type
>::type
, false
, true
, incremental
>::test_all(data);
test_unordered_set < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::auto_member_hook_type
, &value_type::auto_node_
>
>::type
, false
, true
, incremental
>::test_all(data);
return 0;
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
< base_hook_t //cache_begin, compare_hash, incremental
, rebinder<base_hook_t, ConstantTimeSize, ConstantTimeSize, !ConstantTimeSize, !!ConstantTimeSize, Map, DefaultHolder>
>::test_all(data);
//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
< member_hook_t //cache_begin, compare_hash, incremental
, rebinder<member_hook_t, ConstantTimeSize, false, !ConstantTimeSize, false, !ConstantTimeSize, DefaultHolder>
>::test_all(data);
//nonmember
test::test_unordered
< typename testval_traits_t::nonhook_value_traits //cache_begin, compare_hash, incremental
, rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, false, false, false, Map, DefaultHolder>
>::test_all(data);
}
};
int main()
{
test_main_template<void*, false, true>()();
test_main_template<smart_ptr<void>, false, true>()();
test_main_template<void*, true, true>()();
test_main_template<smart_ptr<void>, true, true>()();
test_main_template<void*, false, false>()();
test_main_template<smart_ptr<void>, false, false>()();
test_main_template<void*, true, true>()();
test_main_template<smart_ptr<void>, true, false>()();
//VoidPointer x ConstantTimeSize x Map x DefaultHolder
//void pointer
test_main_template<void*, false, false, false>::execute();
test_main_template<void*, false, true, false>::execute();
test_main_template<void*, true, false, false>::execute();
test_main_template<void*, true, true, false>::execute();
//smart_ptr
test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, true, false>::execute();
////bounded_ptr (bool ConstantTimeSize, bool Map)
//test_main_template_bptr< false, false >::execute();
//test_main_template_bptr< false, true >::execute();
//test_main_template_bptr< true, false >::execute();
//test_main_template_bptr< true, true >::execute();
return boost::report_errors();
}