early-access version 3088

This commit is contained in:
pineappleEA
2022-11-05 15:35:56 +01:00
parent 4e4fc25ce3
commit b601909c6d
35519 changed files with 5996896 additions and 860 deletions

View File

@@ -0,0 +1,34 @@
# Boost Intrusive Library Test Jamfile
# (C) Copyright Ion Gaztanaga 2006.
# Use, modification and distribution are subject to the
# Boost Software License, Version 1.0. (See accompanying file
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
# Adapted from John Maddock's TR1 Jamfile.v2
# Copyright John Maddock 2005.
# Use, modification and distribution are subject to the
# Boost Software License, Version 1.0. (See accompanying file
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
# this rule enumerates through all the sources and invokes
# the run rule for each source, the result is a list of all
# the run rules, which we can pass on to the test_suite rule:
rule test_all
{
local all_rules = ;
for local fileb in [ glob *.cpp ]
{
all_rules += [ run $(fileb)
: # additional args
: # test-files
: # requirements
<host-os>windows,<toolset>clang:<linkflags>"-lole32 -loleaut32 -lpsapi -ladvapi32"
] ;
}
return $(all_rules) ;
}
test-suite intrusive_test : [ test_all r ] : ;

View File

@@ -0,0 +1,188 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include<boost/intrusive/any_hook.hpp>
#include<boost/intrusive/slist.hpp>
#include<boost/intrusive/rbtree.hpp>
#include<boost/intrusive/list.hpp>
#include<boost/intrusive/avltree.hpp>
#include<boost/intrusive/sgtree.hpp>
#include<boost/intrusive/splaytree.hpp>
#include<boost/intrusive/treap.hpp>
#include<boost/intrusive/hashtable.hpp>
#include<boost/functional/hash.hpp>
#include <vector> //std::vector
#include <cstddef> //std::size_t
using namespace boost::intrusive;
class MyClass : public any_base_hook<>
{
int int_;
public:
//This is a member hook
any_member_hook<> member_hook_;
MyClass(int i = 0)
: int_(i)
{}
int get() const
{ return this->int_; }
friend bool operator < (const MyClass &l, const MyClass &r)
{ return l.int_ < r.int_; }
friend bool operator == (const MyClass &l, const MyClass &r)
{ return l.int_ == r.int_; }
friend std::size_t hash_value(const MyClass &o)
{ return boost::hash<int>()(o.get()); }
friend bool priority_order(const MyClass &a, const MyClass &b)
{ return a.int_ < b.int_; }
};
void instantiation_test()
{
typedef member_hook< MyClass, any_member_hook<>, &MyClass::member_hook_> MemberHook;
typedef base_hook< any_base_hook<> > BaseHook;
MyClass myclass;
{
slist < MyClass, any_to_slist_hook< BaseHook > > slist_base;
slist_base.push_front(myclass);
}
{
slist < MyClass, any_to_slist_hook< MemberHook > > slist_member;
slist_member.push_front(myclass);
}
{
list < MyClass, any_to_list_hook< BaseHook > > list_base;
list_base.push_front(myclass);
}
{
list < MyClass, any_to_list_hook< MemberHook > > list_member;
list_member.push_front(myclass);
}
{
rbtree < MyClass, any_to_set_hook< BaseHook > > rbtree_base;
rbtree_base.insert_unique(myclass);
}
{
rbtree < MyClass, any_to_set_hook< MemberHook > > rbtree_member;
rbtree_member.insert_unique(myclass);
}
{
avltree < MyClass, any_to_avl_set_hook< BaseHook > > avltree_base;
avltree_base.insert_unique(myclass);
}
{
avltree < MyClass, any_to_avl_set_hook< MemberHook > > avltree_member;
avltree_member.insert_unique(myclass);
}
{
sgtree < MyClass, any_to_bs_set_hook< BaseHook > > sgtree_base;
sgtree_base.insert_unique(myclass);
}
{
sgtree < MyClass, any_to_bs_set_hook< MemberHook > > sgtree_member;
sgtree_member.insert_unique(myclass);
}
{
treap < MyClass, any_to_bs_set_hook< BaseHook > > treap_base;
treap_base.insert_unique(myclass);
}
{
treap < MyClass, any_to_bs_set_hook< MemberHook > > treap_member;
treap_member.insert_unique(myclass);
}
{
splaytree < MyClass, any_to_bs_set_hook< BaseHook > > splaytree_base;
splaytree_base.insert_unique(myclass);
}
{
splaytree < MyClass, any_to_bs_set_hook< MemberHook > > splaytree_member;
splaytree_member.insert_unique(myclass);
}
typedef unordered_bucket<any_to_unordered_set_hook< BaseHook > >::type bucket_type;
typedef unordered_default_bucket_traits<any_to_unordered_set_hook< BaseHook > >::type bucket_traits;
bucket_type buckets[2];
{
hashtable < MyClass, any_to_unordered_set_hook< BaseHook > >
hashtable_base(bucket_traits(&buckets[0], 1));
hashtable_base.insert_unique(myclass);
}
{
hashtable < MyClass, any_to_unordered_set_hook< MemberHook > >
hashtable_member(bucket_traits(&buckets[1], 1));
hashtable_member.insert_unique(myclass);
}
}
bool simple_slist_test()
{
//Define an slist that will store MyClass using the public base hook
typedef any_to_slist_hook< base_hook< any_base_hook<> > >BaseOption;
typedef slist<MyClass, BaseOption, constant_time_size<false> > BaseList;
//Define an slist that will store MyClass using the public member hook
typedef any_to_slist_hook< member_hook<MyClass, any_member_hook<>, &MyClass::member_hook_> > MemberOption;
typedef slist<MyClass, MemberOption> MemberList;
typedef std::vector<MyClass>::iterator VectIt;
typedef std::vector<MyClass>::reverse_iterator VectRit;
//Create several MyClass objects, each one with a different value
std::vector<MyClass> values;
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
BaseList baselist;
MemberList memberlist;
//Now insert them in the reverse order in the base hook list
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
baselist.push_front(*it);
//Now insert them in the same order as in vector in the member hook list
for(BaseList::iterator it(baselist.begin()), itend(baselist.end())
; it != itend; ++it){
memberlist.push_front(*it);
}
//Now test lists
{
BaseList::iterator bit(baselist.begin());
MemberList::iterator mit(memberlist.begin());
VectRit rit(values.rbegin()), ritend(values.rend());
VectIt it(values.begin()), itend(values.end());
//Test the objects inserted in the base hook list
for(; rit != ritend; ++rit, ++bit)
if(&*bit != &*rit) return false;
//Test the objects inserted in the member hook list
for(; it != itend; ++it, ++mit)
if(&*mit != &*it) return false;
}
return true;
}
int main()
{
if(!simple_slist_test())
return 1;
instantiation_test();
return 0;
}

View File

@@ -0,0 +1,156 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2015.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/avl_set.hpp>
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "avl_test_common.hpp"
#include "generic_multiset_test.hpp"
using namespace boost::intrusive;
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type;
template < class Option1 =void
, class Option2 =void
>
struct container
{
typedef avl_multiset
< typename common_t::value_type
, value_traits<ValueTraits>
, constant_time_size<ConstantTimeSize>
, typename common_t::holder_opt
, typename common_t::key_of_value_opt
, Option1
, Option2
> type;
BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value));
};
};
enum HookType
{
Base,
Member,
NonMember
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type>
class test_main_template;
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base>
{
public:
static void execute()
{
typedef testvalue_traits< avl_hooks<VoidPointer> > testval_traits_t;
//base
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::base_value_traits
, typename testval_traits_t::auto_base_value_traits
>::type base_hook_t;
test::test_generic_multiset
< rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member>
{
public:
static void execute()
{
typedef testvalue_traits< avl_hooks<VoidPointer> > testval_traits_t;
//member
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::member_value_traits
, typename testval_traits_t::auto_member_value_traits
>::type member_hook_t;
test::test_generic_multiset
< rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember>
{
public:
static void execute()
{
typedef testvalue_traits< avl_hooks<VoidPointer> > testval_traits_t;
//nonmember
test::test_generic_multiset
< rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template < bool ConstantTimeSize, bool Map >
struct test_main_template_bptr
{
static void execute()
{
typedef BPtr_Value_Traits< AVLTree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_multiset
< rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
int main()
{
//Combinations: VoidPointer x ConstantTimeSize x DefaultHolder x Map
//Minimize them selecting different combinations for raw and smart pointers
//Start with ('false', 'false', 'false') in sets and 'false', 'false', 'true' in multisets
//void pointer
test_main_template<void*, false, false, false, Base>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false, Member>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false, Base>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false, Member>::execute();
test_main_template<void*, true, true, true, NonMember>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true, Base>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true, Member>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute();
//test_main_template<smart_ptr<void>, true, true, false>::execute();
//test_main_template<smart_ptr<void>, true, true, true>::execute();
//bounded_ptr (bool ConstantTimeSize, bool Map)
test_main_template_bptr< false, false >::execute();
//test_main_template_bptr< false, true >::execute();
//test_main_template_bptr< true, false >::execute();
test_main_template_bptr< true, true >::execute();
return boost::report_errors();
}

View File

@@ -0,0 +1,156 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2015.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/avl_set.hpp>
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "avl_test_common.hpp"
#include "generic_set_test.hpp"
using namespace boost::intrusive;
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type;
template < class Option1 =void
, class Option2 =void
>
struct container
{
typedef avl_set
< typename common_t::value_type
, value_traits<ValueTraits>
, constant_time_size<ConstantTimeSize>
, typename common_t::holder_opt
, typename common_t::key_of_value_opt
, Option1
, Option2
> type;
BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value));
};
};
enum HookType
{
Base,
Member,
NonMember
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type>
class test_main_template;
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base>
{
public:
static void execute()
{
typedef testvalue_traits< avl_hooks<VoidPointer> > testval_traits_t;
//base
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::base_value_traits
, typename testval_traits_t::auto_base_value_traits
>::type base_hook_t;
test::test_generic_set
< rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member>
{
public:
static void execute()
{
typedef testvalue_traits< avl_hooks<VoidPointer> > testval_traits_t;
//member
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::member_value_traits
, typename testval_traits_t::auto_member_value_traits
>::type member_hook_t;
test::test_generic_set
< rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember>
{
public:
static void execute()
{
typedef testvalue_traits< avl_hooks<VoidPointer> > testval_traits_t;
//nonmember
test::test_generic_set
< rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template < bool ConstantTimeSize, bool Map >
struct test_main_template_bptr
{
static void execute()
{
typedef BPtr_Value_Traits< AVLTree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_set
< rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
int main()
{
//Combinations: VoidPointer x ConstantTimeSize x DefaultHolder x Map
//Minimize them selecting different combinations for raw and smart pointers
//Start with ('false', 'false', 'false') in sets and 'false', 'false', 'true' in multisets
//void pointer
test_main_template<void*, false, false, false, Base>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false, Member>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false, Base>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false, Member>::execute();
test_main_template<void*, true, true, true, NonMember>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true, Base>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true, Member>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute();
//test_main_template<smart_ptr<void>, true, true, false>::execute();
//test_main_template<smart_ptr<void>, true, true, true>::execute();
//bounded_ptr (bool ConstantTimeSize, bool Map)
test_main_template_bptr< false, false >::execute();
//test_main_template_bptr< false, true >::execute();
//test_main_template_bptr< true, false >::execute();
test_main_template_bptr< true, true >::execute();
return boost::report_errors();
}

View File

@@ -0,0 +1,45 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_TEST_AVL_TEST_COMMON_HPP
#define BOOST_INTRUSIVE_TEST_AVL_TEST_COMMON_HPP
#include <boost/intrusive/avl_set_hook.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include "bs_test_common.hpp"
namespace boost {
namespace intrusive {
template<class VoidPointer>
struct avl_hooks
{
typedef avl_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
typedef avl_set_base_hook
<link_mode<auto_unlink>
, void_pointer<VoidPointer>
, tag<void>
, optimize_size<true> > auto_base_hook_type;
typedef avl_set_member_hook
<void_pointer<VoidPointer>
, optimize_size<true> > member_hook_type;
typedef avl_set_member_hook
< link_mode<auto_unlink>
, void_pointer<VoidPointer> > auto_member_hook_type;
typedef nonhook_node_member< avltree_node_traits<VoidPointer>,
avltree_algorithms
> nonhook_node_member_type;
};
} //namespace intrusive {
} //namespace boost {
#endif //BOOST_INTRUSIVE_TEST_AVL_TEST_COMMON_HPP

View File

@@ -0,0 +1,432 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Matei David 2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOUNDED_POINTER_HPP
#define BOUNDED_POINTER_HPP
#include <iostream>
#include <cstdlib>
#include <cassert>
#include <boost/container/vector.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <boost/move/adl_move_swap.hpp>
template < typename T >
class bounded_pointer;
template < typename T >
class bounded_reference;
template < typename T >
class bounded_allocator;
struct maintain_offset_t{};
template < typename T >
class bounded_pointer
{
private:
void unspecified_bool_type_func() const {}
typedef void (bounded_pointer::*unspecified_bool_type)() const;
public:
typedef typename boost::intrusive::detail::remove_const< T >::type mut_val_t;
typedef bounded_pointer< mut_val_t > non_const_t;
typedef const mut_val_t const_val_t;
typedef bounded_reference<T> reference;
static const unsigned char max_offset = (unsigned char)-1;
bounded_pointer() : m_offset(max_offset) {}
bounded_pointer(const bounded_pointer& other)
: m_offset(other.m_offset)
{}
template<class T2>
bounded_pointer( const bounded_pointer<T2> &other
, typename boost::intrusive::detail::enable_if_convertible<T2*, T*>::type* = 0)
: m_offset(other.m_offset)
{}
bounded_pointer(maintain_offset_t, unsigned char offset)
: m_offset(offset)
{}
bounded_pointer& operator = (const bounded_pointer& other)
{ m_offset = other.m_offset; return *this; }
template <class T2>
typename boost::intrusive::detail::enable_if_convertible<T2*, T*, bounded_pointer&>::type
operator= (const bounded_pointer<T2> & other)
{ m_offset = other.m_offset; return *this; }
non_const_t unconst() const
{ return non_const_t (maintain_offset_t(), this->m_offset); }
static mut_val_t* base()
{
assert(bounded_allocator< mut_val_t >::inited());
return &bounded_allocator< mut_val_t >::m_base[0];
}
static bounded_pointer pointer_to(bounded_reference< T > r) { return &r; }
template<class U>
static bounded_pointer const_cast_from(const bounded_pointer<U> &uptr)
{ return uptr.unconst(); }
operator unspecified_bool_type() const
{
return m_offset != max_offset? &bounded_pointer::unspecified_bool_type_func : 0;
}
T* raw() const
{ return base() + m_offset; }
bounded_reference< T > operator * () const
{ return bounded_reference< T >(*this); }
T* operator -> () const
{ return raw(); }
bounded_pointer& operator ++ ()
{ ++m_offset; return *this; }
bounded_pointer operator ++ (int)
{ bounded_pointer res(*this); ++(*this); return res; }
friend bool operator == (const bounded_pointer& lhs, const bounded_pointer& rhs)
{ return lhs.m_offset == rhs.m_offset; }
friend bool operator != (const bounded_pointer& lhs, const bounded_pointer& rhs)
{ return lhs.m_offset != rhs.m_offset; }
friend bool operator < (const bounded_pointer& lhs, const bounded_pointer& rhs)
{ return lhs.m_offset < rhs.m_offset; }
friend bool operator <= (const bounded_pointer& lhs, const bounded_pointer& rhs)
{ return lhs.m_offset <= rhs.m_offset; }
friend bool operator >= (const bounded_pointer& lhs, const bounded_pointer& rhs)
{ return lhs.m_offset >= rhs.m_offset; }
friend bool operator > (const bounded_pointer& lhs, const bounded_pointer& rhs)
{ return lhs.m_offset > rhs.m_offset; }
friend std::ostream& operator << (std::ostream& os, const bounded_pointer& ptr)
{
os << static_cast< int >(ptr.m_offset);
return os;
}
private:
template <typename> friend class bounded_pointer;
friend class bounded_reference< T >;
friend class bounded_allocator< T >;
unsigned char m_offset;
}; // class bounded_pointer
template < typename T >
class bounded_reference
{
public:
typedef typename boost::intrusive::detail::remove_const< T >::type mut_val_t;
typedef const mut_val_t const_val_t;
typedef bounded_pointer< T > pointer;
static const unsigned char max_offset = pointer::max_offset;
bounded_reference()
: m_offset(max_offset)
{}
bounded_reference(const bounded_reference& other)
: m_offset(other.m_offset)
{}
T& raw() const
{ assert(m_offset != max_offset); return *(bounded_pointer< T >::base() + m_offset); }
operator T& () const
{ assert(m_offset != max_offset); return raw(); }
bounded_pointer< T > operator & () const
{ assert(m_offset != max_offset); bounded_pointer< T > res; res.m_offset = m_offset; return res; }
bounded_reference& operator = (const T& rhs)
{ assert(m_offset != max_offset); raw() = rhs; return *this; }
bounded_reference& operator = (const bounded_reference& rhs)
{ assert(m_offset != max_offset); raw() = rhs.raw(); return *this; }
template<class T2>
bounded_reference( const bounded_reference<T2> &other
, typename boost::intrusive::detail::enable_if_convertible<T2*, T*>::type* = 0)
: m_offset(other.m_offset)
{}
template <class T2>
typename boost::intrusive::detail::enable_if_convertible<T2*, T*, bounded_reference&>::type
operator= (const bounded_reference<T2> & other)
{ m_offset = other.m_offset; return *this; }
friend std::ostream& operator << (std::ostream& os, const bounded_reference< T >& ref)
{
os << "[bptr=" << static_cast< int >(ref.m_offset) << ",deref=" << ref.raw() << "]";
return os;
}
// the copy asop is shallow; we need swap overload to shuffle a vector of references
friend void swap(bounded_reference& lhs, bounded_reference& rhs)
{ ::boost::adl_move_swap(lhs.m_offset, rhs.m_offset); }
private:
template <typename> friend class bounded_reference;
friend class bounded_pointer< T >;
bounded_reference(bounded_pointer< T > bptr) : m_offset(bptr.m_offset) { assert(m_offset != max_offset); }
unsigned char m_offset;
}; // class bounded_reference
template < typename T >
class bounded_allocator
{
public:
typedef T value_type;
typedef bounded_pointer< T > pointer;
static const unsigned char max_offset = pointer::max_offset;
pointer allocate(size_t n)
{
assert(inited());
assert(n == 1);(void)n;
pointer p;
unsigned char i;
for (i = 0; i < max_offset && m_in_use[i]; ++i);
assert(i < max_offset);
p.m_offset = i;
m_in_use[p.m_offset] = true;
++m_in_use_count;
return p;
}
void deallocate(pointer p, size_t n)
{
assert(inited());
assert(n == 1);(void)n;
assert(m_in_use[p.m_offset]);
m_in_use[p.m_offset] = false;
--m_in_use_count;
}
// static methods
static void init()
{
assert(m_in_use.empty());
m_in_use = boost::container::vector< bool >(max_offset, false);
// allocate non-constructed storage
m_base = static_cast< T* >(::operator new [] (max_offset * sizeof(T)));
}
static bool inited()
{
return m_in_use.size() == max_offset;
}
static bool is_clear()
{
assert(inited());
for (unsigned char i = 0; i < max_offset; ++i)
{
if (m_in_use[i])
{
return false;
}
}
return true;
}
static void destroy()
{
// deallocate storage without destructors
::operator delete [] (m_base);
m_in_use.clear();
}
private:
friend class bounded_pointer< T >;
friend class bounded_pointer< const T >;
static T* m_base;
static boost::container::vector< bool > m_in_use;
static std::size_t m_in_use_count;
}; // class bounded_allocator
template <class BoundedAllocator>
class bounded_allocator_scope
{
public:
bounded_allocator_scope()
{ BoundedAllocator::init(); }
~bounded_allocator_scope()
{
assert(BoundedAllocator::is_clear());
BoundedAllocator::destroy();
}
};
template < typename T >
T* bounded_allocator< T >::m_base = 0;
template < typename T >
boost::container::vector< bool > bounded_allocator< T >::m_in_use;
template < typename T >
std::size_t bounded_allocator< T >::m_in_use_count;
template < typename T >
class bounded_reference_cont
: private boost::container::vector< bounded_reference< T > >
{
private:
typedef T val_type;
typedef boost::container::vector< bounded_reference< T > > Base;
typedef bounded_allocator< T > allocator_type;
typedef bounded_pointer< T > pointer;
public:
typedef typename Base::value_type value_type;
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
typedef typename Base::reference reference;
typedef typename Base::const_reference const_reference;
typedef typename Base::reverse_iterator reverse_iterator;
typedef typename Base::const_reverse_iterator const_reverse_iterator;
using Base::begin;
using Base::rbegin;
using Base::end;
using Base::rend;
using Base::front;
using Base::back;
using Base::size;
using Base::operator[];
using Base::push_back;
explicit bounded_reference_cont(size_t n = 0)
: Base(), m_allocator()
{
for (size_t i = 0; i < n; ++i){
pointer p = m_allocator.allocate(1);
BOOST_TRY{
new (p.raw()) val_type();
}
BOOST_CATCH(...){
m_allocator.deallocate(p, 1);
BOOST_RETHROW
}
BOOST_CATCH_END
Base::push_back(*p);
}
}
bounded_reference_cont(const bounded_reference_cont& other)
: Base(), m_allocator(other.m_allocator)
{ *this = other; }
template < typename InputIterator >
bounded_reference_cont(InputIterator it_start, InputIterator it_end)
: Base(), m_allocator()
{
for (InputIterator it = it_start; it != it_end; ++it){
pointer p = m_allocator.allocate(1);
new (p.raw()) val_type(*it);
Base::push_back(*p);
}
}
template <typename InputIterator>
void assign(InputIterator it_start, InputIterator it_end)
{
this->clear();
for (InputIterator it = it_start; it != it_end;){
pointer p = m_allocator.allocate(1);
new (p.raw()) val_type(*it++);
Base::push_back(*p);
}
}
~bounded_reference_cont()
{ clear(); }
void clear()
{
while (!Base::empty()){
pointer p = &Base::back();
p->~val_type();
m_allocator.deallocate(p, 1);
Base::pop_back();
}
}
bounded_reference_cont& operator = (const bounded_reference_cont& other)
{
if (&other != this){
clear();
for (typename Base::const_iterator it = other.begin(); it != other.end(); ++it){
pointer p = m_allocator.allocate(1);
new (p.raw()) val_type(*it);
Base::push_back(*p);
}
}
return *this;
}
private:
allocator_type m_allocator;
}; // class bounded_reference_cont
template < typename T >
class bounded_pointer_holder
{
public:
typedef T value_type;
typedef bounded_pointer< value_type > pointer;
typedef bounded_pointer< const value_type > const_pointer;
typedef bounded_allocator< value_type > allocator_type;
bounded_pointer_holder() : _ptr(allocator_type().allocate(1))
{ new (_ptr.raw()) value_type(); }
~bounded_pointer_holder()
{
_ptr->~value_type();
allocator_type().deallocate(_ptr, 1);
}
const_pointer get_node () const
{ return _ptr; }
pointer get_node ()
{ return _ptr; }
private:
const pointer _ptr;
}; // class bounded_pointer_holder
#endif

View File

@@ -0,0 +1,270 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Matei David 2014
// (C) Copyright Ion Gaztanaga 2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_BPTR_VALUE_HPP
#define BOOST_INTRUSIVE_BPTR_VALUE_HPP
#include <cassert>
#include <iostream>
#include "bounded_pointer.hpp"
#include "common_functors.hpp"
#include "int_holder.hpp"
#include <boost/intrusive/link_mode.hpp>
namespace boost {
namespace intrusive {
struct BPtr_Value
{
static const bool constant_time_size = true;
explicit BPtr_Value(int value = 42)
: value_(value)
{}
BPtr_Value(const BPtr_Value& rhs)
: value_(rhs.value_)
{}
~BPtr_Value()
{
if (is_linked())
{
assert(false);
}
}
// testvalue is used in boost::container::vector and thus prev and next
// have to be handled appropriately when copied:
BPtr_Value& operator = (const BPtr_Value& src)
{
if (is_linked())
{
assert(false);
}
value_ = src.value_;
return *this;
}
// value
int_holder value_;
// list node hooks
bounded_pointer< BPtr_Value > m_previous;
bounded_pointer< BPtr_Value > m_next;
// tree node hooks
bounded_pointer< BPtr_Value > m_parent;
bounded_pointer< BPtr_Value > m_l_child;
bounded_pointer< BPtr_Value > m_r_child;
signed char m_extra;
const int_holder &get_int_holder() const
{ return value_; }
int int_value() const
{ return value_.int_value(); }
bool is_linked() const
{ return m_previous || m_next || m_parent || m_l_child || m_r_child; }
friend bool operator< (const BPtr_Value &other1, const BPtr_Value &other2)
{ return other1.value_ < other2.value_; }
friend bool operator< (int other1, const BPtr_Value &other2)
{ return other1 < other2.value_; }
friend bool operator< (const BPtr_Value &other1, int other2)
{ return other1.value_ < other2; }
friend bool operator> (const BPtr_Value &other1, const BPtr_Value &other2)
{ return other1.value_ > other2.value_; }
friend bool operator> (int other1, const BPtr_Value &other2)
{ return other1 > other2.value_; }
friend bool operator> (const BPtr_Value &other1, int other2)
{ return other1.value_ > other2; }
friend bool operator== (const BPtr_Value &other1, const BPtr_Value &other2)
{ return other1.value_ == other2.value_; }
friend bool operator== (int other1, const BPtr_Value &other2)
{ return other1 == other2.value_; }
friend bool operator== (const BPtr_Value &other1, int other2)
{ return other1.value_ == other2; }
friend bool operator!= (const BPtr_Value &other1, const BPtr_Value &other2)
{ return !(other1 == other2); }
friend bool operator!= (int other1, const BPtr_Value &other2)
{ return !(other1 == other2.value_); }
friend bool operator!= (const BPtr_Value &other1, int other2)
{ return !(other1.value_ == other2); }
}; // class BPtr_Value
std::ostream& operator<<(std::ostream& s, const BPtr_Value& t)
{ return s << t.value_.int_value(); }
template < typename Node_Algorithms >
void swap_nodes(bounded_reference< BPtr_Value > lhs, bounded_reference< BPtr_Value > rhs)
{
Node_Algorithms::swap_nodes(
boost::intrusive::pointer_traits< bounded_pointer< BPtr_Value > >::pointer_to(lhs),
boost::intrusive::pointer_traits< bounded_pointer< BPtr_Value > >::pointer_to(rhs));
}
struct List_BPtr_Node_Traits
{
typedef BPtr_Value val_t;
typedef val_t node;
typedef bounded_pointer< val_t > node_ptr;
typedef bounded_pointer< const val_t > const_node_ptr;
static node_ptr get_previous(const_node_ptr p) { return p->m_previous; }
static void set_previous(node_ptr p, node_ptr prev) { p->m_previous = prev; }
static node_ptr get_next(const_node_ptr p) { return p->m_next; }
static void set_next(node_ptr p, node_ptr next) { p->m_next = next; }
};
struct Tree_BPtr_Node_Traits
{
typedef BPtr_Value val_t;
typedef val_t node;
typedef bounded_pointer< val_t > node_ptr;
typedef bounded_pointer< const val_t > const_node_ptr;
static node_ptr get_parent(const_node_ptr p) { return p->m_parent; }
static void set_parent(node_ptr p, node_ptr parent) { p->m_parent = parent; }
static node_ptr get_left(const_node_ptr p) { return p->m_l_child; }
static void set_left(node_ptr p, node_ptr l_child) { p->m_l_child = l_child; }
static node_ptr get_right(const_node_ptr p) { return p->m_r_child; }
static void set_right(node_ptr p, node_ptr r_child) { p->m_r_child = r_child; }
};
struct RBTree_BPtr_Node_Traits
: public Tree_BPtr_Node_Traits
{
typedef signed char color;
typedef Tree_BPtr_Node_Traits::node_ptr node_ptr;
typedef Tree_BPtr_Node_Traits::const_node_ptr const_node_ptr;
static color get_color(const_node_ptr p) { return p->m_extra; }
static void set_color(node_ptr p, color c) { p->m_extra = c; }
static color black() { return 0; }
static color red() { return 1; }
};
struct AVLTree_BPtr_Node_Traits
: public Tree_BPtr_Node_Traits
{
typedef signed char balance;
typedef Tree_BPtr_Node_Traits::node_ptr node_ptr;
typedef Tree_BPtr_Node_Traits::const_node_ptr const_node_ptr;
static balance get_balance(const_node_ptr p) { return p->m_extra; }
static void set_balance(node_ptr p, balance b) { p->m_extra = b; }
static balance negative() { return -1; }
static balance zero() { return 0; }
static balance positive() { return 1; }
};
template < typename NodeTraits >
struct BPtr_Value_Traits
{
typedef NodeTraits node_traits;
typedef typename node_traits::val_t value_type;
typedef typename node_traits::node_ptr node_ptr;
typedef typename node_traits::const_node_ptr const_node_ptr;
typedef node_ptr pointer;
typedef const_node_ptr const_pointer;
typedef bounded_reference< value_type > reference;
typedef bounded_reference< const value_type > const_reference;
typedef BPtr_Value_Traits<NodeTraits> * value_traits_ptr;
static const boost::intrusive::link_mode_type link_mode = boost::intrusive::safe_link;
static const_node_ptr to_node_ptr(const_reference v) { return &v; }
static node_ptr to_node_ptr(reference v) { return &v; }
static const_pointer to_value_ptr(const_node_ptr p) { return p; }
static pointer to_value_ptr(node_ptr p) { return p; }
};
template < typename >
struct ValueContainer;
template <>
struct ValueContainer< BPtr_Value >
{
typedef bounded_reference_cont< BPtr_Value > type;
};
namespace test{
template <>
class new_cloner< BPtr_Value >
{
public:
typedef BPtr_Value value_type;
typedef bounded_pointer< value_type > pointer;
typedef bounded_reference< const value_type > const_reference;
typedef bounded_allocator< value_type > allocator_type;
pointer operator () (const_reference r)
{
pointer p = allocator_type().allocate(1);
new (p.raw()) value_type(r);
return p;
}
};
template <>
class new_nonconst_cloner< BPtr_Value >
{
public:
typedef BPtr_Value value_type;
typedef bounded_pointer< value_type > pointer;
typedef bounded_reference< value_type > reference;
typedef bounded_allocator< value_type > allocator_type;
pointer operator () (reference r)
{
pointer p = allocator_type().allocate(1);
new (p.raw()) value_type(r);
return p;
}
};
template <>
class delete_disposer< BPtr_Value >
{
public:
typedef BPtr_Value value_type;
typedef bounded_pointer< value_type > pointer;
typedef bounded_allocator< value_type > allocator_type;
void operator () (pointer p)
{
p->~value_type();
allocator_type().deallocate(p, 1);
}
};
} // namespace test
} // namespace intrusive
} // namespace boost
#endif

View File

@@ -0,0 +1,157 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2015.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/bs_set.hpp>
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "bs_test_common.hpp"
#include "generic_multiset_test.hpp"
using namespace boost::intrusive;
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type;
template < class Option1 =void
, class Option2 =void
>
struct container
{
typedef bs_multiset
< typename common_t::value_type
, value_traits<ValueTraits>
, constant_time_size<ConstantTimeSize>
, typename common_t::holder_opt
, typename common_t::key_of_value_opt
, Option1
, Option2
> type;
BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value));
};
};
enum HookType
{
Base,
Member,
NonMember
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type>
class test_main_template;
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//base
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::base_value_traits
, typename testval_traits_t::auto_base_value_traits
>::type base_hook_t;
test::test_generic_multiset
< rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//member
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::member_value_traits
, typename testval_traits_t::auto_member_value_traits
>::type member_hook_t;
test::test_generic_multiset
< rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//nonmember
test::test_generic_multiset
< rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template < bool ConstantTimeSize, bool Map >
struct test_main_template_bptr
{
static void execute()
{
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_multiset
< rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
int main()
{
//Combinations: VoidPointer x ConstantTimeSize x DefaultHolder x Map
//Minimize them selecting different combinations for raw and smart pointers
//Start with ('false', 'false', 'false') in sets and 'false', 'false', 'true' in multisets
//void pointer
test_main_template<void*, false, false, false, Base>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false, Member>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false, Base>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false, Member>::execute();
test_main_template<void*, true, true, true, NonMember>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true, Base>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true, Member>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute();
//test_main_template<smart_ptr<void>, true, true, false>::execute();
//test_main_template<smart_ptr<void>, true, true, true>::execute();
//bounded_ptr (bool ConstantTimeSize, bool Map)
test_main_template_bptr< false, false >::execute();
//test_main_template_bptr< false, true >::execute();
//test_main_template_bptr< true, false >::execute();
test_main_template_bptr< true, true >::execute();
//test_main_template_bptr< true, true >::execute();
return boost::report_errors();
}

View File

@@ -0,0 +1,155 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2015.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/bs_set.hpp>
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "generic_set_test.hpp"
#include "bs_test_common.hpp"
using namespace boost::intrusive;
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type;
template < class Option1 =void
, class Option2 =void
>
struct container
{
typedef bs_set
< typename common_t::value_type
, value_traits<ValueTraits>
, constant_time_size<ConstantTimeSize>
, typename common_t::holder_opt
, typename common_t::key_of_value_opt
, Option1
, Option2
> type;
BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value));
};
};
enum HookType
{
Base,
Member,
NonMember
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type>
class test_main_template;
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//base
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::base_value_traits
, typename testval_traits_t::auto_base_value_traits
>::type base_hook_t;
test::test_generic_set
< rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//member
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::member_value_traits
, typename testval_traits_t::auto_member_value_traits
>::type member_hook_t;
test::test_generic_set
< rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//nonmember
test::test_generic_set
< rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template < bool ConstantTimeSize, bool Map >
struct test_main_template_bptr
{
static void execute()
{
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_set
< rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
int main()
{
//Combinations: VoidPointer x ConstantTimeSize x DefaultHolder x Map
//Minimize them selecting different combinations for raw and smart pointers
//Start with ('false', 'false', 'false') in sets and 'false', 'false', 'true' in multisets
//void pointer
test_main_template<void*, false, false, false, Base>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false, Member>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false, Base>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false, Member>::execute();
test_main_template<void*, true, true, true, NonMember>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true, Base>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true, Member>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute();
//test_main_template<smart_ptr<void>, true, true, false>::execute();
//test_main_template<smart_ptr<void>, true, true, true>::execute();
//bounded_ptr (bool ConstantTimeSize, bool Map)
test_main_template_bptr< false, false >::execute();
//test_main_template_bptr< false, true >::execute();
//test_main_template_bptr< true, false >::execute();
test_main_template_bptr< true, true >::execute();
return boost::report_errors();
}

View File

@@ -0,0 +1,67 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_TEST_BS_TEST_COMMON_HPP
#define BOOST_INTRUSIVE_TEST_BS_TEST_COMMON_HPP
#include <boost/intrusive/bs_set_hook.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include "bptr_value.hpp"
#include "test_common.hpp"
namespace boost {
namespace intrusive {
template<class VoidPointer>
struct bs_hooks
{
typedef bs_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
typedef bs_set_base_hook
<link_mode<auto_unlink>
, void_pointer<VoidPointer>
, tag<void> > auto_base_hook_type;
typedef bs_set_member_hook
<void_pointer<VoidPointer> > member_hook_type;
typedef bs_set_member_hook
< link_mode<auto_unlink>
, void_pointer<VoidPointer> > auto_member_hook_type;
typedef nonhook_node_member< tree_node_traits<VoidPointer>,
bstree_algorithms
> nonhook_node_member_type;
};
template < class ValueTraits, bool DefaultHolder, bool Map >
struct tree_rebinder_common
{
typedef typename ValueTraits::value_type value_type;
typedef typename detail::if_c
< DefaultHolder
, typename detail::if_c
< detail::is_same<value_type, BPtr_Value>::value
, header_holder_type< bounded_pointer_holder< BPtr_Value > >
, void
>::type
, header_holder_type< heap_node_holder< typename ValueTraits::node_ptr > >
>::type holder_opt;
typedef typename detail::if_c
< Map, key_of_value<int_holder_key_of_value<value_type> >, void
>::type key_of_value_opt;
typedef typename detail::if_c
< Map, priority_of_value<int_priority_of_value<value_type> >, void
>::type prio_of_value_opt;
};
} //namespace intrusive {
} //namespace boost {
#endif //BOOST_INTRUSIVE_TEST_BS_TEST_COMMON_HPP

View File

@@ -0,0 +1,234 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
//////////////////////////////////////////////////////////////////////////////
//User define
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME func0to3
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 3
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace func0to3ns {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME func1to2
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 2
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace func1to2ns {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME func3to3
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 3
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 3
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace func3to3ns {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME func0to0
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace func0to0ns {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
///////////////////
///////////////////
// TEST CODE
///////////////////
///////////////////
struct functor
{
//func0to3
void func0to3();
void func0to3(const int&);
void func0to3(const int&, const int&);
void func0to3(const int&, const int&, const int&);
//func1to2
void func1to2(const int&);
void func1to2(const int&, const int&);
//func3to3
void func3to3(const int&, const int&, const int&);
//func0to0
void func0to0();
};
struct functor2
{
void func0to3(char*);
void func0to3(int, char*);
void func0to3(int, char*, double);
void func0to3(const int&, char*, void *);
//func1to2
void func1to2(char*);
void func1to2(int, char*);
void func1to2(int, char*, double);
//func3to3
void func3to3(const int&, char*, void *);
};
struct functor3
{
};
struct functor4
{
//func0to3
void func0to3(...);
template<class T> void func0to3(int, const T &);
template<class T> void func0to3(const T &);
template<class T, class U> void func0to3(int, const T &, const U &);
//func1to2
template<class T> void func1to2(int, const T &);
template<class T> void func1to2(const T &);
template<class T, class U> void func1to2(int, const T &, const U &);
//func3to3
void func3to3(...);
template<class T, class U> void func3to3(int, const T &, const U &);
};
int main()
{
#if !defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED)
{ //func0to3 0 arg
using func0to3ns::has_member_function_callable_with_func0to3;
int check1[ has_member_function_callable_with_func0to3<functor>::value ? 1 : -1];
int check2[!has_member_function_callable_with_func0to3<functor2>::value ? 1 : -1];
int check3[!has_member_function_callable_with_func0to3<functor3>::value ? 1 : -1];
int check4[ has_member_function_callable_with_func0to3<functor4>::value ? 1 : -1];
(void)check1;
(void)check2;
(void)check3;
(void)check4;
}
{ //func0to0 0 arg
using func0to0ns::has_member_function_callable_with_func0to0;
int check1[ has_member_function_callable_with_func0to0<functor>::value ? 1 : -1];
int check2[!has_member_function_callable_with_func0to0<functor2>::value ? 1 : -1];
int check3[!has_member_function_callable_with_func0to0<functor3>::value ? 1 : -1];
(void)check1;
(void)check2;
(void)check3;
}
#endif
{ //func0to3 1arg
using func0to3ns::has_member_function_callable_with_func0to3;
int check1[ has_member_function_callable_with_func0to3<functor, int>::value ? 1 : -1];
int check2[!has_member_function_callable_with_func0to3<functor, char*>::value ? 1 : -1];
int check3[!has_member_function_callable_with_func0to3<functor2, int>::value ? 1 : -1];
int check4[ has_member_function_callable_with_func0to3<functor2, char*>::value ? 1 : -1];
int check5[!has_member_function_callable_with_func0to3<functor3, int>::value ? 1 : -1];
int check6[!has_member_function_callable_with_func0to3<functor3, char*>::value ? 1 : -1];
int check7[ has_member_function_callable_with_func0to3<functor4, int>::value ? 1 : -1];
int check8[ has_member_function_callable_with_func0to3<functor4, char*>::value ? 1 : -1];
(void)check1;
(void)check2;
(void)check3;
(void)check4;
(void)check5;
(void)check6;
(void)check7;
(void)check8;
}
{ //func1to2 1arg
using func1to2ns::has_member_function_callable_with_func1to2;
int check1[ has_member_function_callable_with_func1to2<functor, int>::value ? 1 : -1];
int check2[!has_member_function_callable_with_func1to2<functor, char*>::value ? 1 : -1];
int check3[!has_member_function_callable_with_func1to2<functor2, int>::value ? 1 : -1];
int check4[ has_member_function_callable_with_func1to2<functor2, char*>::value ? 1 : -1];
int check5[!has_member_function_callable_with_func1to2<functor3, int>::value ? 1 : -1];
int check6[!has_member_function_callable_with_func1to2<functor3, char*>::value ? 1 : -1];
int check7[ has_member_function_callable_with_func1to2<functor4, int>::value ? 1 : -1];
int check8[ has_member_function_callable_with_func1to2<functor4, char*>::value ? 1 : -1];
(void)check1;
(void)check2;
(void)check3;
(void)check4;
(void)check5;
(void)check6;
(void)check7;
(void)check8;
}
{ //func0to3 2arg
using func0to3ns::has_member_function_callable_with_func0to3;
int check1[ has_member_function_callable_with_func0to3<functor, int, int>::value ? 1 : -1];
int check2[!has_member_function_callable_with_func0to3<functor, int, char*>::value ? 1 : -1];
int check3[!has_member_function_callable_with_func0to3<functor2, int, int>::value ? 1 : -1];
int check4[ has_member_function_callable_with_func0to3<functor2, int, char*>::value ? 1 : -1];
int check5[!has_member_function_callable_with_func0to3<functor3, int, int>::value ? 1 : -1];
int check6[!has_member_function_callable_with_func0to3<functor3, int, char*>::value ? 1 : -1];
int check7[ has_member_function_callable_with_func0to3<functor4, int, char*>::value ? 1 : -1];
(void)check1;
(void)check2;
(void)check3;
(void)check4;
(void)check5;
(void)check6;
(void)check7;
}
{ //func1to2 2arg
using func1to2ns::has_member_function_callable_with_func1to2;
int check1[ has_member_function_callable_with_func1to2<functor, int, int>::value ? 1 : -1];
int check2[!has_member_function_callable_with_func1to2<functor, int, char*>::value ? 1 : -1];
int check3[!has_member_function_callable_with_func1to2<functor2, int, int>::value ? 1 : -1];
int check4[ has_member_function_callable_with_func1to2<functor2, int, char*>::value ? 1 : -1];
int check5[!has_member_function_callable_with_func1to2<functor3, int, int>::value ? 1 : -1];
int check6[!has_member_function_callable_with_func1to2<functor3, int, char*>::value ? 1 : -1];
int check7[ has_member_function_callable_with_func1to2<functor4, int, char*>::value ? 1 : -1];
(void)check1;
(void)check2;
(void)check3;
(void)check4;
(void)check5;
(void)check6;
(void)check7;
}
{ //func0to3 3arg
using func0to3ns::has_member_function_callable_with_func0to3;
int check1[ has_member_function_callable_with_func0to3<functor, int, int, int>::value ? 1 : -1];
int check2[!has_member_function_callable_with_func0to3<functor, int, char*, int>::value ? 1 : -1];
int check3[!has_member_function_callable_with_func0to3<functor2, int, int, int>::value ? 1 : -1];
int check4[ has_member_function_callable_with_func0to3<functor2, int, char*, void*>::value ? 1 : -1];
int check5[!has_member_function_callable_with_func0to3<functor3, int, int, int>::value ? 1 : -1];
int check6[!has_member_function_callable_with_func0to3<functor3, int, char*, void*>::value ? 1 : -1];
int check7[ has_member_function_callable_with_func0to3<functor4, int, char*, int>::value ? 1 : -1];
(void)check1;
(void)check2;
(void)check3;
(void)check4;
(void)check5;
(void)check6;
(void)check7;
}
{ //func3to3 3arg
using func3to3ns::has_member_function_callable_with_func3to3;
int check1[ has_member_function_callable_with_func3to3<functor, int, int, int>::value ? 1 : -1];
int check2[!has_member_function_callable_with_func3to3<functor, int, char*, int>::value ? 1 : -1];
int check3[!has_member_function_callable_with_func3to3<functor2, int, int, int>::value ? 1 : -1];
int check4[ has_member_function_callable_with_func3to3<functor2, int, char*, void*>::value ? 1 : -1];
int check5[!has_member_function_callable_with_func3to3<functor3, int, int, int>::value ? 1 : -1];
int check6[!has_member_function_callable_with_func3to3<functor3, int, char*, void*>::value ? 1 : -1];
int check7[ has_member_function_callable_with_func3to3<functor4, int, char*, int>::value ? 1 : -1];
(void)check1;
(void)check2;
(void)check3;
(void)check4;
(void)check5;
(void)check6;
(void)check7;
}
return 0;
}

View File

@@ -0,0 +1,12 @@
#include <boost/config.hpp>
#ifndef BOOST_NO_CXX11_DECLTYPE
# define BOOST_NO_CXX11_DECLTYPE
# include "callable_with.cpp"
#else
int main()
{
return 0;
}
#endif

View File

@@ -0,0 +1,12 @@
#include <boost/config.hpp>
#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
# define BOOST_NO_CXX11_VARIADIC_TEMPLATES
# include "callable_with.cpp"
#else
int main()
{
return 0;
}
#endif

View File

@@ -0,0 +1,88 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_TEST_COMMON_FUNCTORS_HPP
#define BOOST_INTRUSIVE_TEST_COMMON_FUNCTORS_HPP
#include<boost/intrusive/detail/iterator.hpp>
#include<boost/intrusive/detail/mpl.hpp>
#include<boost/static_assert.hpp>
#include<boost/move/detail/to_raw_pointer.hpp>
namespace boost {
namespace intrusive {
namespace test {
template<class T>
class delete_disposer
{
public:
template <class Pointer>
void operator()(Pointer p)
{
typedef typename boost::intrusive::iterator_traits<Pointer>::value_type value_type;
BOOST_STATIC_ASSERT(( detail::is_same<T, value_type>::value ));
delete boost::movelib::to_raw_pointer(p);
}
};
template<class T>
class new_cloner
{
public:
T *operator()(const T &t)
{ return new T(t); }
};
template<class T>
class new_nonconst_cloner
{
public:
T *operator()(T &t)
{ return new T(t); }
};
template<class T>
class new_default_factory
{
public:
T *operator()()
{ return new T(); }
};
class empty_disposer
{
public:
template<class T>
void operator()(const T &)
{}
};
struct any_less
{
template<class T, class U>
bool operator()(const T &t, const U &u) const
{ return t < u; }
};
struct any_greater
{
template<class T, class U>
bool operator()(const T &t, const U &u) const
{ return t > u; }
};
} //namespace test {
} //namespace intrusive {
} //namespace boost {
#endif

View File

@@ -0,0 +1,226 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/core/lightweight_test.hpp>
#include <cstddef>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/avl_set.hpp>
#include <boost/intrusive/bs_set.hpp>
#include <boost/intrusive/sg_set.hpp>
#include <boost/intrusive/splay_set.hpp>
#include <boost/intrusive/treap_set.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <boost/static_assert.hpp>
#include "itestvalue.hpp"
using namespace boost::intrusive;
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reverse_iterator)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_reverse_iterator)
template<bool Value>
struct boolean
{
static const bool value = Value;
};
template<class A, class B>
struct pow2_and_equal_sizes
{
static const std::size_t a_size = sizeof(A);
static const std::size_t b_size = sizeof(B);
static const bool a_b_sizes_equal = a_size == b_size;
static const bool value = !(a_size & (a_size - 1u));
};
template<class Hook>
struct node : Hook
{};
//Avoid testing for uncommon architectures
void test_sizes(boolean<false>, std::size_t)
{}
template<class C>
void test_iterator_sizes(std::size_t size)
{
typedef typename C::iterator iterator;
typedef typename C::const_iterator const_iterator;
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
(::, C, reverse_iterator, iterator) reverse_iterator;
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
(::, C, const_reverse_iterator, const_iterator) const_reverse_iterator;
BOOST_TEST_EQ(sizeof(iterator), size);
BOOST_TEST_EQ(sizeof(const_iterator), size);
BOOST_TEST_EQ(sizeof(iterator), sizeof(reverse_iterator));
BOOST_TEST_EQ(sizeof(const_iterator), size);
BOOST_TEST_EQ(sizeof(const_iterator), sizeof(const_reverse_iterator));
}
//Test sizes for common 32 and 64 bit architectures
void test_sizes(boolean<true>, std::size_t wordsize)
{
{ //list
typedef list<node<list_base_hook<> > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes<c>(wordsize);
}
{
typedef list<node<list_base_hook<> >, constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*2);
test_iterator_sizes<c>(wordsize);
}
{
typedef list< node< list_base_hook<> >, header_holder_type< heap_node_holder< list_node<void*>* > > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*2);
test_iterator_sizes<c>(wordsize);
}
{
typedef list< node< list_base_hook<> >, constant_time_size<false>, header_holder_type< heap_node_holder< list_node<void*>* > > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*1);
test_iterator_sizes<c>(wordsize);
}
{ //slist
typedef slist<node< slist_base_hook<> > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*2);
test_iterator_sizes<c>(wordsize);
}
{
typedef slist<node< slist_base_hook<> >, constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*1);
test_iterator_sizes<c>(wordsize);
}
{
typedef slist<node< slist_base_hook<> >, cache_last<true> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes<c>(wordsize);
}
{ //set
typedef set<node< set_base_hook<> > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*5);
test_iterator_sizes<c>(wordsize);
}
{
typedef set<node< set_base_hook<> > , constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*4);
test_iterator_sizes<c>(wordsize);
}
{
typedef set<node< set_base_hook<optimize_size<true> > > , constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes<c>(wordsize);
}
{
typedef set< node< set_base_hook<> >, header_holder_type< heap_node_holder< rbtree_node<void*>* > > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*2);
test_iterator_sizes<c>(wordsize);
}
{
typedef set< node< set_base_hook<> >, constant_time_size<false>, header_holder_type< heap_node_holder< rbtree_node<void*>* > > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*1);
test_iterator_sizes<c>(wordsize);
}
{ //avl
typedef avl_set<node< avl_set_base_hook<> > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*5);
test_iterator_sizes<c>(wordsize);
}
{
typedef avl_set<node< avl_set_base_hook<> > , constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*4);
test_iterator_sizes<c>(wordsize);
}
{
typedef avl_set<node< avl_set_base_hook<optimize_size<true> > > , constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes<c>(wordsize);
}
{
typedef avl_set< node< avl_set_base_hook<> >, header_holder_type< heap_node_holder< avltree_node<void*>* > > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*2);
test_iterator_sizes<c>(wordsize);
}
{
typedef avl_set< node< avl_set_base_hook<> >, constant_time_size<false>, header_holder_type< heap_node_holder< avltree_node<void*>* > > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*1);
test_iterator_sizes<c>(wordsize);
}
{ //bs
typedef bs_set<node< bs_set_base_hook<> > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*4);
test_iterator_sizes<c>(wordsize);
}
{
typedef bs_set<node< bs_set_base_hook<> > , constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes<c>(wordsize);
}
{ //splay
typedef splay_set<node< bs_set_base_hook<> > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*4);
test_iterator_sizes<c>(wordsize);
}
{
typedef splay_set<node< bs_set_base_hook<> > , constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes<c>(wordsize);
}
{ //scapegoat
typedef sg_set<node< bs_set_base_hook<> > > c;
BOOST_TEST_EQ(sizeof(c), (wordsize*5+sizeof(float)*2));
test_iterator_sizes<c>(wordsize);
}
{ //treap
typedef treap_set<node< bs_set_base_hook<> > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*4);
test_iterator_sizes<c>(wordsize);
}
{
typedef treap_set<node< bs_set_base_hook<> > , constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes<c>(wordsize);
}
{ //unordered
typedef unordered_set<node< unordered_set_base_hook<> > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes<c>(wordsize*2);
}
{
typedef unordered_set<node< unordered_set_base_hook<> > , power_2_buckets<true> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes<c>(wordsize*2);
}
{
typedef unordered_set<node< unordered_set_base_hook<> >, constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*2);
test_iterator_sizes<c>(wordsize*2);
}
{
typedef unordered_set<node< unordered_set_base_hook< optimize_multikey<true> > >, constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*2);
test_iterator_sizes<c>(wordsize*2);
}
{
typedef unordered_set<node< unordered_set_base_hook< optimize_multikey<true> > >, incremental<true> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*4);
test_iterator_sizes<c>(wordsize*2);
}
}
int main()
{
test_sizes(boolean< pow2_and_equal_sizes<std::size_t, void*>::value >(), sizeof(std::size_t));
return ::boost::report_errors();
}

View File

@@ -0,0 +1,129 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/unordered_set.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/static_assert.hpp>
#include <vector>
using namespace boost::intrusive;
class MyClass : public unordered_set_base_hook<>
{
int int_;
public:
MyClass(int i = 0) : int_(i)
{}
unordered_set_member_hook<> member_hook_;
friend bool operator==(const MyClass &l, const MyClass &r)
{ return l.int_ == r.int_; }
friend std::size_t hash_value(const MyClass &v)
{ return boost::hash_value(v.int_); }
};
struct uset_value_traits
{
typedef slist_node_traits<void*> node_traits;
typedef node_traits::node_ptr node_ptr;
typedef node_traits::const_node_ptr const_node_ptr;
typedef MyClass value_type;
typedef MyClass * pointer;
typedef const MyClass * const_pointer;
static const link_mode_type link_mode = normal_link;
static node_ptr to_node_ptr (value_type &value)
{ return node_ptr(&value); }
static const_node_ptr to_node_ptr (const value_type &value)
{ return const_node_ptr(&value); }
static pointer to_value_ptr(node_ptr n)
{ return static_cast<value_type*>(n); }
static const_pointer to_value_ptr(const_node_ptr n)
{ return static_cast<const value_type*>(n); }
};
//Base
typedef base_hook< unordered_set_base_hook<> > BaseHook;
typedef unordered_bucket<BaseHook>::type BaseBucketType;
typedef unordered_bucket_ptr<BaseHook>::type BaseBucketPtrType;
typedef unordered_set<MyClass, BaseHook> BaseUset;
//Member
typedef member_hook
< MyClass, unordered_set_member_hook<>
, &MyClass::member_hook_ > MemberHook;
typedef unordered_bucket<MemberHook>::type MemberBucketType;
typedef unordered_bucket_ptr<MemberHook>::type MemberBucketPtrType;
typedef unordered_set<MyClass, MemberHook> MemberUset;
//Explicit
typedef value_traits< uset_value_traits > Traits;
typedef unordered_bucket<Traits>::type TraitsBucketType;
typedef unordered_bucket_ptr<Traits>::type TraitsBucketPtrType;
typedef unordered_set<MyClass, Traits> TraitsUset;
struct uset_bucket_traits
{
//Power of two bucket length
static const std::size_t NumBuckets = 128;
uset_bucket_traits(BaseBucketType *buckets)
: buckets_(buckets)
{}
uset_bucket_traits(const uset_bucket_traits &other)
: buckets_(other.buckets_)
{}
BaseBucketType * bucket_begin() const
{ return buckets_; }
std::size_t bucket_count() const
{ return NumBuckets; }
BaseBucketType *buckets_;
};
typedef unordered_set
<MyClass, bucket_traits<uset_bucket_traits>, power_2_buckets<true> >
BucketTraitsUset;
int main()
{
BOOST_STATIC_ASSERT((detail::is_same<BaseUset::bucket_type, BaseBucketType>::value));
BOOST_STATIC_ASSERT((detail::is_same<MemberUset::bucket_type, MemberBucketType>::value));
BOOST_STATIC_ASSERT((detail::is_same<TraitsUset::bucket_type, TraitsBucketType>::value));
BOOST_STATIC_ASSERT((detail::is_same<BaseBucketType, MemberBucketType>::value));
BOOST_STATIC_ASSERT((detail::is_same<BaseBucketType, TraitsBucketType>::value));
BOOST_STATIC_ASSERT((detail::is_same<BaseBucketPtrType, TraitsBucketPtrType>::value));
BOOST_STATIC_ASSERT((detail::is_same<BaseBucketPtrType, MemberBucketPtrType>::value));
BOOST_STATIC_ASSERT((detail::is_same<BaseBucketPtrType, BaseBucketType*>::value));
typedef std::vector<MyClass>::iterator VectIt;
typedef std::vector<MyClass>::reverse_iterator VectRit;
std::vector<MyClass> values;
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
BaseBucketType buckets[uset_bucket_traits::NumBuckets];
uset_bucket_traits btraits(buckets);
BucketTraitsUset uset(btraits);
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
uset.insert(*it);
for( VectRit it(values.rbegin()), itend(values.rend()); it != itend; ++it){
if(uset.find(*it) == uset.cend()) return 1;
}
return 0;
}

View File

@@ -0,0 +1,166 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <boost/intrusive/splay_set.hpp>
#include <boost/intrusive/avl_set.hpp>
#include <boost/intrusive/sg_set.hpp>
#include <boost/intrusive/treap_set.hpp>
#include <boost/intrusive/bs_set.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include "smart_ptr.hpp"
#include <vector>
using namespace boost::intrusive;
class MyClass
: public list_base_hook
< void_pointer<smart_ptr<void> >, link_mode<safe_link> >
, public slist_base_hook
< void_pointer<smart_ptr<void> >, link_mode<safe_link> >
, public set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<safe_link> >
, public unordered_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<safe_link> >
, public avl_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<safe_link> >
, public bs_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<safe_link> >
{
int int_;
public:
MyClass(int i)
: int_(i)
{}
friend bool operator<(const MyClass &l, const MyClass &r)
{ return l.int_ < r.int_; }
friend bool operator==(const MyClass &l, const MyClass &r)
{ return l.int_ == r.int_; }
friend std::size_t hash_value(const MyClass &v)
{ return boost::hash_value(v.int_); }
friend bool priority_order(const MyClass &l, const MyClass &r)
{ return l.int_ < r.int_; }
};
//Define a list that will store MyClass using the public base hook
typedef list<MyClass> List;
typedef slist<MyClass> Slist;
typedef set<MyClass> Set;
typedef unordered_set<MyClass> USet;
typedef avl_set<MyClass> AvlSet;
typedef splay_set<MyClass> SplaySet;
typedef treap_set<MyClass> TreapSet;
typedef sg_set<MyClass> SgSet;
typedef bs_set<MyClass> BsSet;
int main()
{
typedef std::vector<MyClass>::iterator VectIt;
typedef std::vector<MyClass>::reverse_iterator VectRit;
//Create several MyClass objects, each one with a different value
std::vector<MyClass> values;
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
{
List my_list;
Slist my_slist;
Set my_set;
USet::bucket_type buckets[100];
USet my_uset(USet::bucket_traits(pointer_traits<USet::bucket_ptr>::pointer_to(*buckets), 100));
AvlSet my_avlset;
SplaySet my_splayset;
//Now insert them in the reverse order
//in the base hook intrusive list
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){
my_list.push_front(*it);
my_slist.push_front(*it);
my_set.insert(*it);
my_uset.insert(*it);
my_avlset.insert(*it);
my_splayset.insert(*it);
}
//Now test lists
{
List::const_iterator list_it(my_list.cbegin());
Slist::const_iterator slist_it(my_slist.cbegin());
Set::const_reverse_iterator set_rit(my_set.crbegin());
AvlSet::const_reverse_iterator avl_set_rit(my_avlset.crbegin());
SplaySet::const_reverse_iterator splay_set_rit(my_splayset.crbegin());
VectRit vect_it(values.rbegin()), vect_itend(values.rend());
//Test the objects inserted in the base hook list
for(; vect_it != vect_itend
; ++vect_it, ++list_it
, ++slist_it, ++set_rit
, ++avl_set_rit
, ++splay_set_rit
){
if(&*list_it != &*vect_it) return 1;
if(&*slist_it != &*vect_it) return 1;
if(&*set_rit != &*vect_it) return 1;
if(&*avl_set_rit != &*vect_it) return 1;
if(&*splay_set_rit != &*vect_it)return 1;
if(my_uset.find(*set_rit) == my_uset.cend()) return 1;
}
}
}
//Since treap_set, sg_set & bs_set reuse the hook, treat them apart
{
TreapSet my_treapset;
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){
my_treapset.insert(*it);
}
TreapSet::const_reverse_iterator treap_set_rit(my_treapset.crbegin());
VectRit vect_it(values.rbegin()), vect_itend(values.rend());
for(; vect_it != vect_itend; ++vect_it, ++treap_set_rit){
if(&*treap_set_rit != &*vect_it) return 1;
}
}
{
SgSet my_sgset;
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){
my_sgset.insert(*it);
}
SgSet::const_reverse_iterator sg_set_rit(my_sgset.crbegin());
VectRit vect_it(values.rbegin()), vect_itend(values.rend());
for(; vect_it != vect_itend; ++vect_it, ++sg_set_rit){
if(&*sg_set_rit != &*vect_it) return 1;
}
}
{
BsSet my_bsset;
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){
my_bsset.insert(*it);
}
BsSet::const_reverse_iterator bs_set_rit(my_bsset.crbegin());
VectRit vect_it(values.rbegin()), vect_itend(values.rend());
for(; vect_it != vect_itend; ++vect_it, ++bs_set_rit){
if(&*bs_set_rit != &*vect_it) return 1;
}
}
return 0;
}

View File

@@ -0,0 +1,150 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2010-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/parent_from_member.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <boost/container_hash/hash.hpp>
using namespace boost::intrusive;
struct MyClass
{
MyClass() : order(0) {}
int order;
//This internal type has two hooks
struct InnerNode : public list_base_hook<>, public slist_base_hook<>
, public set_base_hook<>, public unordered_set_base_hook<>
{
list_member_hook<> listhook;
slist_member_hook<> slisthook;
set_member_hook<> sethook;
unordered_set_member_hook<> usethook;
} inner;
friend bool operator < (const MyClass &l, const MyClass &r)
{ return l.order < r.order; }
friend bool operator == (const MyClass &l, const MyClass &r)
{ return l.order == r.order; }
friend std::size_t hash_value(const MyClass &value)
{ return std::size_t(value.order); }
};
//This functor converts between MyClass and the InnerNode member hook
#define InnerMemberHook(TAG, HOOKTYPE, MEMBERNAME)\
struct InnerMemberHookFunctor##TAG \
{\
typedef HOOKTYPE hook_type;\
typedef hook_type* hook_ptr;\
typedef const hook_type* const_hook_ptr;\
typedef MyClass value_type;\
typedef value_type* pointer;\
typedef const value_type* const_pointer;\
\
static hook_ptr to_hook_ptr (value_type &value)\
{ return &value.inner.MEMBERNAME; }\
static const_hook_ptr to_hook_ptr(const value_type &value)\
{ return &value.inner.MEMBERNAME; }\
static pointer to_value_ptr(hook_ptr n)\
{\
return get_parent_from_member<MyClass>\
(get_parent_from_member<MyClass::InnerNode>(n, &MyClass::InnerNode::MEMBERNAME)\
,&MyClass::inner\
);\
}\
static const_pointer to_value_ptr(const_hook_ptr n)\
{\
return get_parent_from_member<MyClass>\
(get_parent_from_member<MyClass::InnerNode>(n, &MyClass::InnerNode::MEMBERNAME)\
,&MyClass::inner\
);\
}\
};\
//
//This functor converts between MyClass and the InnerNode base hook
#define InnerBaseHook(TAG, HOOKTYPE)\
struct InnerBaseHookFunctor##TAG \
{\
typedef HOOKTYPE hook_type;\
typedef hook_type* hook_ptr;\
typedef const hook_type* const_hook_ptr;\
typedef MyClass value_type;\
typedef value_type* pointer;\
typedef const value_type* const_pointer;\
\
static hook_ptr to_hook_ptr (value_type &value)\
{ return &value.inner; }\
static const_hook_ptr to_hook_ptr(const value_type &value)\
{ return &value.inner; }\
static pointer to_value_ptr(hook_ptr n)\
{\
return get_parent_from_member<MyClass>(static_cast<MyClass::InnerNode*>(n),&MyClass::inner);\
}\
static const_pointer to_value_ptr(const_hook_ptr n)\
{\
return get_parent_from_member<MyClass>(static_cast<const MyClass::InnerNode*>(n),&MyClass::inner);\
}\
};\
//
//List
InnerMemberHook(List, list_member_hook<>, listhook)
InnerBaseHook(List, list_base_hook<>)
//Slist
InnerMemberHook(Slist, slist_member_hook<>, slisthook)
InnerBaseHook(Slist, slist_base_hook<>)
//Set
InnerMemberHook(Set, set_member_hook<>, sethook)
InnerBaseHook(Set, set_base_hook<>)
//Unordered Set
InnerMemberHook(USet, unordered_set_member_hook<>, usethook)
InnerBaseHook(USet, unordered_set_base_hook<>)
//Define containers
typedef list < MyClass, function_hook< InnerMemberHookFunctorList> > CustomListMember;
typedef list < MyClass, function_hook< InnerBaseHookFunctorList > > CustomListBase;
typedef slist< MyClass, function_hook< InnerMemberHookFunctorSlist> > CustomSlistMember;
typedef slist< MyClass, function_hook< InnerBaseHookFunctorSlist > > CustomSlistBase;
typedef set < MyClass, function_hook< InnerMemberHookFunctorSet> > CustomSetMember;
typedef set < MyClass, function_hook< InnerBaseHookFunctorSet > > CustomSetBase;
typedef unordered_set< MyClass, function_hook< InnerMemberHookFunctorUSet> > CustomUSetMember;
typedef unordered_set< MyClass, function_hook< InnerBaseHookFunctorUSet > > CustomUSetBase;
int main()
{
MyClass n;
CustomListBase listbase;
CustomListMember listmember;
CustomSlistBase slistbase;
CustomSlistMember slistmember;
CustomSetBase setbase;
CustomSetMember setmember;
CustomUSetBase::bucket_type buckets_uset[1];
CustomUSetBase usetbase(CustomUSetBase::bucket_traits(buckets_uset, 1));
CustomUSetBase::bucket_type buckets_umultiset[1];
CustomUSetMember usetmember(CustomUSetMember::bucket_traits(buckets_umultiset, 1));
listbase.insert(listbase.begin(), n);
listmember.insert(listmember.begin(), n);
slistbase.insert(slistbase.begin(), n);
slistmember.insert(slistmember.begin(), n);
setbase.insert(n);
setmember.insert(n);
usetbase.insert(n);
usetmember.insert(n);
return 0;
}

View File

@@ -0,0 +1,598 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2021.
// (C) Copyright Daniel Steck 2021
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/container/vector.hpp> //vector
#include <boost/intrusive/detail/config_begin.hpp>
#include "common_functors.hpp"
#include <boost/intrusive/options.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/iterator.hpp>
#include <boost/core/lightweight_test.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
namespace boost{
namespace intrusive{
namespace test{
BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(has_splay, splay)
BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(has_rebalance, rebalance)
BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(has_insert_before, insert_before)
BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(is_treap, priority_comp)
template<class ContainerDefiner>
struct test_generic_assoc
{
typedef typename ContainerDefiner::value_cont_type value_cont_type;
static void test_all(value_cont_type&);
static void test_root(value_cont_type&);
static void test_clone(value_cont_type&);
static void test_insert_erase_burst();
static void test_swap_nodes();
template <class Assoc>
static void test_perfect_binary_tree_of_height_2(value_cont_type &values, Assoc &assoc);
static void test_container_from_end(value_cont_type&, detail::true_type);
static void test_container_from_end(value_cont_type&, detail::false_type) {}
static void test_splay_up(value_cont_type&, detail::true_type);
static void test_splay_up(value_cont_type&, detail::false_type) {}
static void test_splay_down(value_cont_type&, detail::true_type);
static void test_splay_down(value_cont_type&, detail::false_type) {}
static void test_rebalance(value_cont_type&, detail::true_type);
static void test_rebalance(value_cont_type&, detail::false_type) {}
static void test_insert_before(value_cont_type&, detail::true_type);
static void test_insert_before(value_cont_type&, detail::false_type) {}
static void test_container_from_iterator(value_cont_type&, detail::true_type);
static void test_container_from_iterator(value_cont_type&, detail::false_type) {}
};
template<class ContainerDefiner>
void test_generic_assoc<ContainerDefiner>::
test_container_from_iterator(value_cont_type& values, detail::true_type)
{
typedef typename ContainerDefiner::template container
<>::type assoc_type;
assoc_type testset(values.begin(), values.end());
typedef typename assoc_type::iterator it_type;
typedef typename assoc_type::const_iterator cit_type;
typedef typename assoc_type::size_type sz_type;
sz_type sz = testset.size();
for(it_type b(testset.begin()), e(testset.end()); b != e; ++b)
{
assoc_type &s = assoc_type::container_from_iterator(b);
const assoc_type &cs = assoc_type::container_from_iterator(cit_type(b));
BOOST_TEST(&s == &cs);
BOOST_TEST(&s == &testset);
s.erase(b);
BOOST_TEST(testset.size() == (sz-1));
s.insert(*b);
BOOST_TEST(testset.size() == sz);
}
}
template<class ContainerDefiner>
void test_generic_assoc<ContainerDefiner>::test_insert_erase_burst()
{
//value_cont_type values;
const std::size_t MaxValues = 200;
value_cont_type values(MaxValues);
for(std::size_t i = 0; i != MaxValues; ++i){
(&values[i])->value_ = (int)i;
}
typedef typename ContainerDefiner::template container
<>::type assoc_type;
typedef typename assoc_type::iterator iterator;
{ //Ordered insertion + erasure
assoc_type testset (values.begin(), values.end());
TEST_INTRUSIVE_SEQUENCE_EXPECTED(testset, testset.begin());
testset.check();
iterator it(testset.begin()), itend(testset.end());
for(std::size_t i = 0; it != itend; ++i){
BOOST_TEST(&*it == &values[i]);
it = testset.erase(it);
testset.check();
}
BOOST_TEST(testset.empty());
}
{ //Now random insertions + erasure
assoc_type testset;
typedef typename value_cont_type::iterator vec_iterator;
boost::container::vector<vec_iterator> it_vector;
//Random insertion
for(vec_iterator it(values.begin()), itend(values.end())
; it != itend
; ++it){
it_vector.push_back(it);
}
for(std::size_t i = 0; i != MaxValues; ++i){
testset.insert(*it_vector[i]);
testset.check();
}
TEST_INTRUSIVE_SEQUENCE_EXPECTED(testset, testset.begin());
//Random erasure
random_shuffle(it_vector.begin(), it_vector.end());
for(std::size_t i = 0; i != MaxValues; ++i){
testset.erase(testset.iterator_to(*it_vector[i]));
testset.check();
}
BOOST_TEST(testset.empty());
}
}
// Perfect binary tree of height 2
// 3 |
// / \ |
// 1 5 |
// / \ / \ |
// 0 2 4 6 |
template<class ContainerDefiner>
template <class Assoc>
void test_generic_assoc<ContainerDefiner>::test_perfect_binary_tree_of_height_2
(value_cont_type &values, Assoc &assoc)
{
//value_cont_type values;
const std::size_t MaxValues = 7;
BOOST_TEST(values.size() == MaxValues);
for(std::size_t i = 0; i != MaxValues; ++i){
(&values[i])->value_ = (int)i;
}
typedef typename Assoc::iterator iterator;
BOOST_TEST( assoc.empty() );
assoc.clear();
const iterator it3 = assoc.insert_before(assoc.end(), values[3]);
const iterator it1 = assoc.insert_before(it3, values[1]);
const iterator it5 = assoc.insert_before(assoc.end(), values[5]);
assoc.insert_before(it1, values[0]);
assoc.insert_before(it3, values[2]);
assoc.insert_before(it5, values[4]);
assoc.insert_before(assoc.end(), values[6]);
}
template<class ContainerDefiner>
void test_generic_assoc<ContainerDefiner>::test_swap_nodes()
{
// Perfect binary tree of height 2
// 3 |
// / \ |
// 1 5 |
// / \ / \ |
// 0 2 4 6 |
typedef typename ContainerDefiner::template container
<>::type assoc_type;
typedef typename assoc_type::value_traits value_traits_t;
typedef typename assoc_type::node_algorithms node_algorithms_t;
const std::size_t MaxValues = 7;
{ //Unrelated swap
value_cont_type values(MaxValues);
assoc_type testset;
test_perfect_binary_tree_of_height_2(values, testset);
node_algorithms_t::swap_nodes
( value_traits_t::to_node_ptr(values[0])
, value_traits_t::to_node_ptr(values[4])
);
BOOST_TEST( (&*iterator_next(testset.begin(), 0) == &values[4]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 1) == &values[1]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 2) == &values[2]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 3) == &values[3]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 4) == &values[0]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 5) == &values[5]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 6) == &values[6]) );
node_algorithms_t::swap_nodes
( value_traits_t::to_node_ptr(values[4])
, value_traits_t::to_node_ptr(values[0])
);
BOOST_TEST( (&*iterator_next(testset.begin(), 0) == &values[0]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 1) == &values[1]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 2) == &values[2]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 3) == &values[3]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 4) == &values[4]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 5) == &values[5]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 6) == &values[6]) );
testset.check();
}
{ //sibling leaf nodes
value_cont_type values(MaxValues);
assoc_type testset;
test_perfect_binary_tree_of_height_2(values, testset);
node_algorithms_t::swap_nodes
( value_traits_t::to_node_ptr(values[0])
, value_traits_t::to_node_ptr(values[2])
);
BOOST_TEST( (&*iterator_next(testset.begin(), 0) == &values[2]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 1) == &values[1]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 2) == &values[0]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 3) == &values[3]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 4) == &values[4]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 5) == &values[5]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 6) == &values[6]) );
node_algorithms_t::swap_nodes
( value_traits_t::to_node_ptr(values[0])
, value_traits_t::to_node_ptr(values[2])
);
BOOST_TEST( (&*iterator_next(testset.begin(), 0) == &values[0]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 1) == &values[1]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 2) == &values[2]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 3) == &values[3]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 4) == &values[4]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 5) == &values[5]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 6) == &values[6]) );
testset.check();
}
{ //sibling nodes
value_cont_type values(MaxValues);
assoc_type testset;
test_perfect_binary_tree_of_height_2(values, testset);
node_algorithms_t::swap_nodes
( value_traits_t::to_node_ptr(values[1])
, value_traits_t::to_node_ptr(values[5])
);
BOOST_TEST( (&*iterator_next(testset.begin(), 0) == &values[0]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 1) == &values[5]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 2) == &values[2]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 3) == &values[3]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 4) == &values[4]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 5) == &values[1]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 6) == &values[6]) );
node_algorithms_t::swap_nodes
( value_traits_t::to_node_ptr(values[1])
, value_traits_t::to_node_ptr(values[5])
);
BOOST_TEST( (&*iterator_next(testset.begin(), 0) == &values[0]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 1) == &values[1]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 2) == &values[2]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 3) == &values[3]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 4) == &values[4]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 5) == &values[5]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 6) == &values[6]) );
testset.check();
}
{ //left child
value_cont_type values(MaxValues);
assoc_type testset;
test_perfect_binary_tree_of_height_2(values, testset);
node_algorithms_t::swap_nodes
( value_traits_t::to_node_ptr(values[0])
, value_traits_t::to_node_ptr(values[1])
);
BOOST_TEST( (&*iterator_next(testset.begin(), 0) == &values[1]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 1) == &values[0]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 2) == &values[2]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 3) == &values[3]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 4) == &values[4]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 5) == &values[5]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 6) == &values[6]) );
node_algorithms_t::swap_nodes
( value_traits_t::to_node_ptr(values[0])
, value_traits_t::to_node_ptr(values[1])
);
BOOST_TEST( (&*iterator_next(testset.begin(), 0) == &values[0]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 1) == &values[1]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 2) == &values[2]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 3) == &values[3]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 4) == &values[4]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 5) == &values[5]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 6) == &values[6]) );
testset.check();
}
{ //right child
value_cont_type values(MaxValues);
assoc_type testset;
test_perfect_binary_tree_of_height_2(values, testset);
node_algorithms_t::swap_nodes
( value_traits_t::to_node_ptr(values[1])
, value_traits_t::to_node_ptr(values[2])
);
BOOST_TEST( (&*iterator_next(testset.begin(), 0) == &values[0]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 1) == &values[2]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 2) == &values[1]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 3) == &values[3]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 4) == &values[4]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 5) == &values[5]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 6) == &values[6]) );
node_algorithms_t::swap_nodes
( value_traits_t::to_node_ptr(values[1])
, value_traits_t::to_node_ptr(values[2])
);
BOOST_TEST( (&*iterator_next(testset.begin(), 0) == &values[0]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 1) == &values[1]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 2) == &values[2]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 3) == &values[3]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 4) == &values[4]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 5) == &values[5]) );
BOOST_TEST( (&*iterator_next(testset.begin(), 6) == &values[6]) );
testset.check();
}
}
template<class ContainerDefiner>
void test_generic_assoc<ContainerDefiner>::test_all(value_cont_type& values)
{
typedef typename ContainerDefiner::template container
<>::type assoc_type;
test_root(values);
test_clone(values);
test_container_from_end(values, detail::bool_< assoc_type::has_container_from_iterator >());
test_splay_up(values, detail::bool_< has_splay< assoc_type >::value >());
test_splay_down(values, detail::bool_< has_splay< assoc_type >::value >());
test_rebalance(values, detail::bool_< has_rebalance< assoc_type >::value >());
test_insert_before(values, detail::bool_< has_insert_before< assoc_type >::value >());
test_insert_erase_burst();
test_swap_nodes();
test_container_from_iterator(values, detail::bool_< assoc_type::has_container_from_iterator >());
}
template<class ContainerDefiner>
void test_generic_assoc<ContainerDefiner>::test_root(value_cont_type& values)
{
typedef typename ContainerDefiner::template container<>::type assoc_type;
typedef typename assoc_type::iterator iterator;
typedef typename assoc_type::const_iterator const_iterator;
assoc_type testset1;
const assoc_type &ctestset1 = testset1;;
BOOST_TEST( testset1.root() == testset1.end());
BOOST_TEST(ctestset1.root() == ctestset1.cend());
BOOST_TEST( testset1.croot() == ctestset1.cend());
testset1.insert(values.begin(), values.end());
iterator i = testset1.root();
iterator i2(i);
BOOST_TEST( i.go_parent().go_parent() == i2);
const_iterator ci = ctestset1.root();
const_iterator ci2(ci);
BOOST_TEST( ci.go_parent().go_parent() == ci2);
ci = testset1.croot();
ci2 = ci;
BOOST_TEST( ci.go_parent().go_parent() == ci2);
}
template<class ContainerDefiner>
void test_generic_assoc<ContainerDefiner>::test_clone(value_cont_type& values)
{
{
typedef typename ContainerDefiner::template container
<>::type assoc_type;
typedef typename assoc_type::value_type value_type;
typedef typename assoc_type::size_type size_type;
assoc_type testset1 (values.begin(), values.end());
assoc_type testset2;
size_type const testset1_oldsize = testset1.size();
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
BOOST_TEST (testset1.size() == testset1_oldsize);
BOOST_TEST (testset2 == testset1);
testset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testset2.empty());
//Now test move clone
testset2.clone_from(boost::move(testset1), test::new_nonconst_cloner<value_type>(), test::delete_disposer<value_type>());
BOOST_TEST (testset2 == testset1);
testset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testset2.empty());
}
}
template<class ContainerDefiner>
void test_generic_assoc<ContainerDefiner>
::test_container_from_end(value_cont_type& values, detail::true_type)
{
typedef typename ContainerDefiner::template container
<>::type assoc_type;
assoc_type testset (values.begin(), values.end());
BOOST_TEST (testset == assoc_type::container_from_end_iterator(testset.end()));
BOOST_TEST (testset == assoc_type::container_from_end_iterator(testset.cend()));
}
template<class ContainerDefiner>
void test_generic_assoc<ContainerDefiner>::test_splay_up
(value_cont_type& values, detail::true_type)
{
typedef typename ContainerDefiner::template container
<>::type assoc_type;
typedef typename assoc_type::iterator iterator;
typedef value_cont_type orig_set_t;
std::size_t num_values;
orig_set_t original_testset;
{
assoc_type testset (values.begin(), values.end());
num_values = testset.size();
original_testset = value_cont_type(testset.begin(), testset.end());
}
for(std::size_t i = 0; i != num_values; ++i){
assoc_type testset (values.begin(), values.end());
{
iterator it = testset.begin();
for(std::size_t j = 0; j != i; ++j, ++it){}
testset.splay_up(it);
}
BOOST_TEST (testset.size() == num_values);
iterator it = testset.begin();
for( typename orig_set_t::const_iterator origit = original_testset.begin()
, origitend = original_testset.end()
; origit != origitend
; ++origit, ++it){
BOOST_TEST(*origit == *it);
}
}
}
template<class ContainerDefiner>
void test_generic_assoc<ContainerDefiner>::test_splay_down
(value_cont_type& values, detail::true_type)
{
typedef typename ContainerDefiner::template container
<>::type assoc_type;
typedef typename assoc_type::iterator iterator;
typedef value_cont_type orig_set_t;
std::size_t num_values;
orig_set_t original_testset;
{
assoc_type testset (values.begin(), values.end());
num_values = testset.size();
original_testset = value_cont_type(testset.begin(), testset.end());
}
for(std::size_t i = 0; i != num_values; ++i){
assoc_type testset (values.begin(), values.end());
BOOST_TEST(testset.size() == num_values);
{
iterator it = testset.begin();
for(std::size_t j = 0; j != i; ++j, ++it){}
BOOST_TEST(*it == *testset.splay_down(*it));
}
BOOST_TEST (testset.size() == num_values);
iterator it = testset.begin();
for( typename orig_set_t::const_iterator origit = original_testset.begin()
, origitend = original_testset.end()
; origit != origitend
; ++origit, ++it){
BOOST_TEST(*origit == *it);
}
}
}
template<class ContainerDefiner>
void test_generic_assoc<ContainerDefiner>::test_rebalance
(value_cont_type& values, detail::true_type)
{
typedef typename ContainerDefiner::template container
<>::type assoc_type;
typedef value_cont_type orig_set_t;
orig_set_t original_testset;
{
assoc_type testset (values.begin(), values.end());
original_testset.assign(testset.begin(), testset.end());
}
{
assoc_type testset(values.begin(), values.end());
testset.rebalance();
TEST_INTRUSIVE_SEQUENCE_EXPECTED(original_testset, testset.begin());
}
{
std::size_t numdata;
{
assoc_type testset(values.begin(), values.end());
numdata = testset.size();
}
for(int i = 0; i != (int)numdata; ++i){
assoc_type testset(values.begin(), values.end());
typename assoc_type::iterator it = testset.begin();
for(int j = 0; j != i; ++j) ++it;
testset.rebalance_subtree(it);
TEST_INTRUSIVE_SEQUENCE_EXPECTED(original_testset, testset.begin());
}
}
}
template<class ContainerDefiner>
void test_generic_assoc<ContainerDefiner>::test_insert_before
(value_cont_type& values, detail::true_type)
{
typedef typename ContainerDefiner::template container
<>::type assoc_type;
{
assoc_type testset;
typedef typename value_cont_type::iterator vec_iterator;
for(vec_iterator it(values.begin()), itend(values.end())
; it != itend
; ++it){
testset.push_back(*it);
}
BOOST_TEST(testset.size() == values.size());
TEST_INTRUSIVE_SEQUENCE_EXPECTED(values, testset.begin());
}
{
assoc_type testset;
typedef typename value_cont_type::iterator vec_iterator;
for(vec_iterator it(--values.end()); true; --it){
testset.push_front(*it);
if(it == values.begin()){
break;
}
}
BOOST_TEST(testset.size() == values.size());
TEST_INTRUSIVE_SEQUENCE_EXPECTED(values, testset.begin());
}
{
assoc_type testset;
typedef typename value_cont_type::iterator vec_iterator;
typename assoc_type::iterator it_pos =
testset.insert_before(testset.end(), *values.rbegin());
testset.insert_before(testset.begin(), *values.begin());
for(vec_iterator it(++values.begin()), itend(--values.end())
; it != itend
; ++it){
testset.insert_before(it_pos, *it);
}
BOOST_TEST(testset.size() == values.size());
TEST_INTRUSIVE_SEQUENCE_EXPECTED(values, testset.begin());
}
}
}}} //namespace boost::intrusive::test
#include <boost/intrusive/detail/config_end.hpp>

View File

@@ -0,0 +1,324 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/container/vector.hpp>
#include "common_functors.hpp"
#include <boost/core/lightweight_test.hpp>
#include <boost/intrusive/options.hpp>
#include <boost/intrusive/detail/iterator.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
#include "generic_assoc_test.hpp"
#include <typeinfo>
namespace boost{
namespace intrusive{
namespace test{
template<class ContainerDefiner>
struct test_generic_multiset
{
typedef typename ContainerDefiner::value_cont_type value_cont_type;
static void test_all();
static void test_sort(value_cont_type&);
static void test_insert(value_cont_type&);
static void test_swap(value_cont_type&);
static void test_merge(value_cont_type&);
static void test_find(value_cont_type&);
static void test_impl();
};
template<class ContainerDefiner>
void test_generic_multiset<ContainerDefiner>::test_all ()
{
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
value_cont_type values (6);
for (std::size_t i = 0u; i < 6u; ++i)
(&values[i])->value_ = random_init[i];
typedef typename ContainerDefiner::template container
<>::type multiset_type;
{
multiset_type testset(values.begin(), values.end());
test::test_container(testset);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_common_unordered_and_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_non_unique_container(testset, values);
}
test_sort(values);
test_insert(values);
test_swap(values);
test_merge(values);
test_find(values);
test_impl();
test_generic_assoc<ContainerDefiner>::test_all(values);
}
//test case due to an error in tree implementation:
template<class ContainerDefiner>
void test_generic_multiset<ContainerDefiner>::test_impl()
{
value_cont_type values (5);
for (std::size_t i = 0u; i < 5u; ++i)
(&values[i])->value_ = (int)i;
typedef typename ContainerDefiner::template container
<>::type multiset_type;
multiset_type testset;
for (std::size_t i = 0; i < 5u; ++i)
testset.insert (values[i]);
testset.erase (testset.iterator_to (values[0]));
testset.erase (testset.iterator_to (values[1]));
testset.insert (values[1]);
testset.erase (testset.iterator_to (values[2]));
testset.erase (testset.iterator_to (values[3]));
}
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
template<class ContainerDefiner>
void test_generic_multiset<ContainerDefiner>::test_sort(value_cont_type& values)
{
typedef typename ContainerDefiner::template container
<>::type multiset_type;
multiset_type testset1 (values.begin(), values.end());
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
testset1.clear();
BOOST_TEST (testset1.empty());
typedef typename ContainerDefiner::template container
<compare<even_odd>
>::type multiset_type2;
multiset_type2 testset2 (values.begin(), values.begin() + 6);
{ int init_values [] = { 5, 3, 1, 4, 2, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.rbegin() ); }
BOOST_TEST (testset2.begin()->value_ == 2);
BOOST_TEST (testset2.rbegin()->value_ == 5);
}
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
template<class ContainerDefiner>
void test_generic_multiset<ContainerDefiner>::test_insert(value_cont_type& values)
{
typedef typename ContainerDefiner::template container
<>::type multiset_type;
multiset_type testset;
testset.insert(values.begin() + 2, values.begin() + 5);
testset.check();
{ int init_values [] = { 1, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); }
typename multiset_type::iterator i = testset.begin();
BOOST_TEST (i->value_ == 1);
i = testset.insert (i, values[0]);
testset.check();
BOOST_TEST (&*i == &values[0]);
{ int init_values [] = { 5, 4, 3, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset.rbegin() ); }
i = testset.iterator_to (values[2]);
BOOST_TEST (&*i == &values[2]);
i = multiset_type::s_iterator_to (values[2]);
BOOST_TEST (&*i == &values[2]);
testset.erase(i);
testset.check();
{ int init_values [] = { 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); }
}
//test: insert (seq-version), swap, erase (seq-version), size:
template<class ContainerDefiner>
void test_generic_multiset<ContainerDefiner>::test_swap(value_cont_type& values)
{
typedef typename ContainerDefiner::template container
<>::type multiset_type;
multiset_type testset1 (values.begin(), values.begin() + 2);
multiset_type testset2;
testset2.insert (values.begin() + 2, values.begin() + 6);
testset1.swap (testset2);
{ int init_values [] = { 1, 2, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
{ int init_values [] = { 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
testset1.erase (testset1.iterator_to(values[5]), testset1.end());
BOOST_TEST (testset1.size() == 1);
BOOST_TEST (&*testset1.begin() == &values[3]);
}
template<class ContainerDefiner>
void test_generic_multiset<ContainerDefiner>::test_merge(value_cont_type& values)
{
typedef typename ContainerDefiner::template container
<>::type multiset_type;
typedef typename multiset_type::key_of_value key_of_value;
typedef typename multiset_type::key_type key_type;
typedef typename ContainerDefiner::template container
< compare< std::greater<key_type> > >::type multiset_greater_type;
//original vector: 3, 2, 4, 1, 5, 2
//2,3
multiset_type testset1 (values.begin(), values.begin() + 2);
//5, 4, 2, 1
multiset_greater_type testset2;
testset2.insert (values.begin() + 2, values.begin() + 6);
testset2.merge(testset1);
testset1.check();
testset2.check();
BOOST_TEST (testset1.empty());
BOOST_TEST (testset2.size() == 6);
{ int init_values [] = { 5, 4, 3, 2, 2, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
value_cont_type cmp_val_cont(1);
typename value_cont_type::reference cmp_val = cmp_val_cont.front();
(&cmp_val)->value_ = 2;
BOOST_TEST (*testset2.find(key_of_value()(cmp_val)) == values[5]);
BOOST_TEST (*testset2.find(2, any_greater()) == values[5]);
BOOST_TEST (&*(++testset2.find(key_of_value()(cmp_val))) == &values[1]);
testset1.merge(testset2);
testset1.check();
testset2.check();
BOOST_TEST (testset1.size() == 6);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
BOOST_TEST (*testset1.find(key_of_value()(cmp_val)) == values[5]);
BOOST_TEST (*testset1.find(2, any_less()) == values[5]);
BOOST_TEST (&*(++testset1.find(key_of_value()(cmp_val))) == &values[1]);
BOOST_TEST (testset2.empty());
}
//test: find, equal_range (lower_bound, upper_bound):
template<class ContainerDefiner>
void test_generic_multiset<ContainerDefiner>::test_find(value_cont_type& values)
{
typedef typename ContainerDefiner::template container
<>::type multiset_type;
typedef typename multiset_type::key_of_value key_of_value;
multiset_type testset (values.begin(), values.end());
typedef typename multiset_type::iterator iterator;
{
value_cont_type cmp_val_cont(1);
typename value_cont_type::reference cmp_val = cmp_val_cont.front();
(&cmp_val)->value_ = 2;
iterator i = testset.find (key_of_value()(cmp_val));
BOOST_TEST (i == testset.find (2, any_less()));
BOOST_TEST (i->value_ == 2);
BOOST_TEST ((++i)->value_ == 2);
std::pair<iterator,iterator> range = testset.equal_range (key_of_value()(cmp_val));
BOOST_TEST(range == testset.equal_range (2, any_less()));
BOOST_TEST (range.first->value_ == 2);
BOOST_TEST (range.second->value_ == 3);
BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 2);
(&cmp_val)->value_ = 7;
BOOST_TEST (testset.find(key_of_value()(cmp_val)) == testset.end());
BOOST_TEST (testset.find (7, any_less()) == testset.end());
}
{ //1, 2, 2, 3, 4, 5
std::pair<iterator,iterator> range;
value_cont_type cmp_val_cont(2);
typename value_cont_type::reference cmp_val_lower = cmp_val_cont.front();
typename value_cont_type::reference cmp_val_upper = cmp_val_cont.back();
{
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 2;
//left-closed, right-closed
range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, true);
BOOST_TEST (range == testset.bounded_range (1, 2, any_less(), true, true));
BOOST_TEST (range.first->value_ == 1);
BOOST_TEST (range.second->value_ == 3);
BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 3);
}
const multiset_type &const_testset = testset;
typedef typename multiset_type::const_iterator const_iterator;
std::pair<const_iterator, const_iterator> const_range;
{
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 2;
const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false);
BOOST_TEST (const_range == const_testset.bounded_range (1, 2, any_less(), true, false));
BOOST_TEST (const_range.first->value_ == 1);
BOOST_TEST (const_range.second->value_ == 2);
BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1);
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 3;
range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false);
BOOST_TEST (range == testset.bounded_range (1, 3, any_less(), true, false));
BOOST_TEST (range.first->value_ == 1);
BOOST_TEST (range.second->value_ == 3);
BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 3);
}
{
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 2;
const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), false, true);
BOOST_TEST (const_range == const_testset.bounded_range (1, 2, any_less(), false, true));
BOOST_TEST (const_range.first->value_ == 2);
BOOST_TEST (const_range.second->value_ == 3);
BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 2);
}
{
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 2;
range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), false, false);
BOOST_TEST (range == testset.bounded_range (1, 2, any_less(), false, false));
BOOST_TEST (range.first->value_ == 2);
BOOST_TEST (range.second->value_ == 2);
BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 0);
}
{
(&cmp_val_lower)->value_ = 5;
(&cmp_val_upper)->value_ = 6;
const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false);
BOOST_TEST (const_range == const_testset.bounded_range (5, 6, any_less(), true, false));
BOOST_TEST (const_range.first->value_ == 5);
BOOST_TEST (const_range.second == const_testset.end());
BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1);
}
}
}
}}} //namespace boost::intrusive::test
#include <boost/intrusive/detail/config_end.hpp>

View File

@@ -0,0 +1,405 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/container/vector.hpp>
#include <boost/intrusive/detail/config_begin.hpp>
#include "common_functors.hpp"
#include <boost/core/lightweight_test.hpp>
#include <boost/intrusive/options.hpp>
#include <boost/intrusive/detail/iterator.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
#include "generic_assoc_test.hpp"
#include <typeinfo>
#include <boost/intrusive/priority_compare.hpp>
namespace boost{
namespace intrusive{
namespace test{
template<class ContainerDefiner>
struct test_generic_set
{
static void test_all();
private:
typedef typename ContainerDefiner::value_cont_type value_cont_type;
static void test_sort(value_cont_type&);
static void test_insert(value_cont_type&);
static void test_insert_advanced(value_cont_type&, detail::true_type);
static void test_insert_advanced(value_cont_type&, detail::false_type);
static void test_swap(value_cont_type&);
static void test_merge(value_cont_type&);
static void test_find(value_cont_type&);
static void test_impl();
};
template<class ContainerDefiner>
void test_generic_set<ContainerDefiner>::test_all()
{
typedef typename ContainerDefiner::template container
<>::type set_type;
{
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
value_cont_type values(6);
for (std::size_t i = 0; i < 6u; ++i)
(&values[i])->value_ = random_init[i];
{
set_type testset(values.begin(), values.end());
test::test_container(testset);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_common_unordered_and_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_unique_container(testset, values);
}
test_sort(values);
test_insert(values);
test_insert_advanced(values, detail::bool_< is_treap< set_type >::value >());
test_swap(values);
test_merge(values);
test_find(values);
test_impl();
test_generic_assoc<ContainerDefiner>::test_all(values);
}
{
value_cont_type values(6);
for (std::size_t i = 0; i < 6u; ++i)
(&values[i])->value_ = (int)i+1;
set_type testset(values.begin(), values.end());
test::test_iterator_bidirectional(testset);
}
}
//test case due to an error in tree implementation:
template<class ContainerDefiner>
void test_generic_set<ContainerDefiner>::test_impl()
{
value_cont_type values (5);
for (std::size_t i = 0; i < 5u; ++i)
(&values[i])->value_ = (int)i;
typedef typename ContainerDefiner::template container
<>::type set_type;
set_type testset;
for (std::size_t i = 0; i < 5u; ++i)
testset.insert (values[i]);
testset.erase (testset.iterator_to (values[0]));
testset.erase (testset.iterator_to (values[1]));
testset.insert (values[1]);
testset.erase (testset.iterator_to (values[2]));
testset.erase (testset.iterator_to (values[3]));
}
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
template<class ContainerDefiner>
void test_generic_set<ContainerDefiner>::test_sort(value_cont_type& values)
{
typedef typename ContainerDefiner::template container
<>::type set_type;
set_type testset1 (values.begin(), values.end());
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
testset1.clear();
BOOST_TEST (testset1.empty());
typedef typename ContainerDefiner::template container
< compare<even_odd> >::type set_type2;
set_type2 testset2 (values.begin(), values.begin() + 6);
{ int init_values [] = { 5, 3, 1, 4, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.rbegin() ); }
BOOST_TEST (testset2.begin()->value_ == 2);
BOOST_TEST (testset2.rbegin()->value_ == 5);
}
//test: insert, const_iterator, const_reverse_iterator, erase, s_iterator_to:
template<class ContainerDefiner>
void test_generic_set<ContainerDefiner>::test_insert(value_cont_type& values)
{
typedef typename ContainerDefiner::template container
<>::type set_type;
{
set_type testset;
testset.insert(values.begin() + 2, values.begin() + 5);
testset.check();
const set_type& const_testset = testset;
{ int init_values [] = { 1, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
typename set_type::iterator i = testset.begin();
BOOST_TEST (i->value_ == 1);
i = testset.insert (i, values[0]);
testset.check();
BOOST_TEST (&*i == &values[0]);
{ int init_values [] = { 5, 4, 3, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset.rbegin() ); }
i = testset.iterator_to (values[2]);
BOOST_TEST (&*i == &values[2]);
i = set_type::s_iterator_to(values[2]);
BOOST_TEST (&*i == &values[2]);
typedef typename value_cont_type::const_reference const_reference;
typename set_type::const_iterator ic;
ic = testset.iterator_to (static_cast< const_reference >(values[2]));
BOOST_TEST (&*ic == &values[2]);
ic = set_type::s_iterator_to (static_cast< const_reference >(values[2]));
BOOST_TEST (&*ic == &values[2]);
testset.erase (i);
testset.check();
{ int init_values [] = { 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); }
}
}
// treap version
template<class ValueType, class KeyType>
struct prio_comp
: priority_compare<int>
{
bool operator()(const ValueType &v, const KeyType &k) const
{ return this->priority_compare<int>::operator()(v.int_value(), k.int_value()); }
bool operator()(const KeyType &k, const ValueType &v) const
{ return this->priority_compare<int>::operator()(k.int_value(), v.int_value()); }
};
template<class ContainerDefiner>
void test_generic_set<ContainerDefiner>::test_insert_advanced
(value_cont_type& values, detail::true_type)
{
typedef typename ContainerDefiner::template container
<>::type set_type;
typedef typename set_type::key_of_value key_of_value;
typedef typename set_type::priority_of_value priority_of_value;
typedef typename set_type::value_type value_type;
typedef priority_compare<> prio_comp_t;
{
set_type testset;
testset.insert(values.begin(), values.end());
testset.check();
value_type v(1);
typename set_type::insert_commit_data data;
BOOST_TEST ((!testset.insert_check(1, any_less(), 1, prio_comp_t(), data).second));
BOOST_TEST ((!testset.insert_check(testset.begin(), 1, any_less(), 1, prio_comp_t(), data).second));
BOOST_TEST ((!testset.insert_check(key_of_value()(v), priority_of_value()(v), data).second));
BOOST_TEST ((!testset.insert_check(testset.begin(), key_of_value()(v), priority_of_value()(v), data).second));
}
}
//test: insert, const_iterator, const_reverse_iterator, erase, s_iterator_to:
template<class ContainerDefiner>
void test_generic_set<ContainerDefiner>::test_insert_advanced
(value_cont_type& values, detail::false_type)
{
typedef typename ContainerDefiner::template container
<>::type set_type;
typedef typename set_type::key_of_value key_of_value;
typedef typename set_type::value_type value_type;
{
set_type testset;
testset.insert(values.begin(), values.end());
testset.check();
value_type v(1);
typename set_type::insert_commit_data data;
BOOST_TEST ((!testset.insert_check(1, any_less(), data).second));
BOOST_TEST ((!testset.insert_check(key_of_value()(v), data).second));
BOOST_TEST ((!testset.insert_check(testset.begin(), 1, any_less(), data).second));
BOOST_TEST ((!testset.insert_check(testset.begin(), key_of_value()(v), data).second));
}
}
//test: insert (seq-version), swap, erase (seq-version), size:
template<class ContainerDefiner>
void test_generic_set<ContainerDefiner>::test_swap(value_cont_type& values)
{
typedef typename ContainerDefiner::template container
<>::type set_type;
set_type testset1 (values.begin(), values.begin() + 2);
set_type testset2;
testset2.insert (values.begin() + 2, values.begin() + 6);
testset1.swap (testset2);
{ int init_values [] = { 1, 2, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
{ int init_values [] = { 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
testset1.erase (testset1.iterator_to(values[5]), testset1.end());
BOOST_TEST (testset1.size() == 1);
// BOOST_TEST (&testset1.front() == &values[3]);
BOOST_TEST (&*testset1.begin() == &values[3]);
}
template<class ContainerDefiner>
void test_generic_set<ContainerDefiner>::test_merge(value_cont_type& values)
{
typedef typename ContainerDefiner::template container
<>::type set_type;
typedef typename set_type::key_type key_type;
typedef typename ContainerDefiner::template container
< compare< std::greater<key_type> > >::type set_greater_type;
//2,3
set_type testset1 (values.begin(), values.begin() + 2);
//5, 4, 2, 1
set_greater_type testset2;
testset2.insert (values.begin() + 2, values.begin() + 6);
testset2.merge(testset1);
testset1.check();
testset2.check();
BOOST_TEST (testset1.size() == 1);
{ int init_values [] = { 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
BOOST_TEST (&*testset1.begin() == &values[1]);
BOOST_TEST (testset2.size() == 5);
{ int init_values [] = { 5, 4, 3, 2, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
testset1.merge(testset2);
testset1.check();
testset2.check();
BOOST_TEST (testset1.size() == 5);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
BOOST_TEST (testset2.size() == 1);
{ int init_values [] = { 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
BOOST_TEST (&*testset2.begin() == &values[5]);
}
//test: find, equal_range (lower_bound, upper_bound), bounded_range:
template<class ContainerDefiner>
void test_generic_set<ContainerDefiner>::test_find(value_cont_type& values)
{
typedef typename ContainerDefiner::template container
<>::type set_type;
set_type testset (values.begin(), values.end());
typedef typename set_type::iterator iterator;
typedef typename set_type::const_iterator const_iterator;
typedef typename set_type::key_of_value key_of_value;
typedef typename value_cont_type::reference reference;
{
//value_type cmp_val;
value_cont_type cmp_val_cont(1);
reference cmp_val = cmp_val_cont.front();
(&cmp_val)->value_ = 2;
iterator i = testset.find(key_of_value()(cmp_val));
BOOST_TEST (i == testset.find(2, any_less()));
BOOST_TEST (i->value_ == 2);
BOOST_TEST ((++i)->value_ != 2);
std::pair<iterator,iterator> range = testset.equal_range (key_of_value()(cmp_val));
BOOST_TEST(range == testset.equal_range (2, any_less()));
BOOST_TEST (range.first->value_ == 2);
BOOST_TEST (range.second->value_ == 3);
BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 1);
(&cmp_val)->value_ = 7;
BOOST_TEST (testset.find (key_of_value()(cmp_val)) == testset.end());
BOOST_TEST (testset.find (7, any_less()) == testset.end());
}
{
const set_type &const_testset = testset;
std::pair<iterator,iterator> range;
std::pair<const_iterator, const_iterator> const_range;
//value_type cmp_val_lower, cmp_val_upper;
value_cont_type cmp_val_cont(2);
reference cmp_val_lower = cmp_val_cont.front();
reference cmp_val_upper = cmp_val_cont.back();
{
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 2;
//left-closed, right-closed
range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, true);
BOOST_TEST (range == testset.bounded_range (1, 2, any_less(), true, true));
BOOST_TEST (range.first->value_ == 1);
BOOST_TEST (range.second->value_ == 3);
BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 2);
}
{
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 2;
const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false);
BOOST_TEST (const_range == const_testset.bounded_range (1, 2, any_less(), true, false));
BOOST_TEST (const_range.first->value_ == 1);
BOOST_TEST (const_range.second->value_ == 2);
BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1);
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 3;
range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false);
BOOST_TEST (range == testset.bounded_range (1, 3, any_less(), true, false));
BOOST_TEST (range.first->value_ == 1);
BOOST_TEST (range.second->value_ == 3);
BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 2);
}
{
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 2;
const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), false, true);
BOOST_TEST (const_range == const_testset.bounded_range (1, 2, any_less(), false, true));
BOOST_TEST (const_range.first->value_ == 2);
BOOST_TEST (const_range.second->value_ == 3);
BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1);
}
{
(&cmp_val_lower)->value_ = 1;
(&cmp_val_upper)->value_ = 2;
range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), false, false);
BOOST_TEST (range == testset.bounded_range (1, 2, any_less(), false, false));
BOOST_TEST (range.first->value_ == 2);
BOOST_TEST (range.second->value_ == 2);
BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 0);
}
{
(&cmp_val_lower)->value_ = 5;
(&cmp_val_upper)->value_ = 6;
const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false);
BOOST_TEST (const_range == const_testset.bounded_range (5, 6, any_less(), true, false));
BOOST_TEST (const_range.first->value_ == 5);
BOOST_TEST (const_range.second == const_testset.end());
BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1);
}
}
}
}}} //namespace boost::intrusive::test
#include <boost/intrusive/detail/config_end.hpp>

View File

@@ -0,0 +1,117 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_INT_HOLDER_HPP
#define BOOST_INTRUSIVE_DETAIL_INT_HOLDER_HPP
#include <boost/functional/hash/hash.hpp>
namespace boost{
namespace intrusive{
struct int_holder
{
explicit int_holder(int value = 0)
: int_(value)
{}
int_holder &operator=(int value)
{ int_ = value; return *this; }
int int_value() const
{ return int_; }
friend bool operator==(const int_holder &l, const int_holder &r)
{ return l.int_ == r.int_; }
friend bool operator!=(const int_holder &l, const int_holder &r)
{ return l.int_ != r.int_; }
friend bool operator<(const int_holder &l, const int_holder &r)
{ return l.int_ < r.int_; }
friend bool operator>(const int_holder &l, const int_holder &r)
{ return l.int_ > r.int_; }
friend bool operator<=(const int_holder &l, const int_holder &r)
{ return l.int_ <= r.int_; }
friend bool operator>=(const int_holder &l, const int_holder &r)
{ return l.int_ >= r.int_; }
///
friend bool operator==(int l, const int_holder &r)
{ return l == r.int_; }
friend bool operator!=(int l, const int_holder &r)
{ return l != r.int_; }
friend bool operator<(int l, const int_holder &r)
{ return l < r.int_; }
friend bool operator>(int l, const int_holder &r)
{ return l > r.int_; }
friend bool operator<=(int l, const int_holder &r)
{ return l <= r.int_; }
friend bool operator>=(int l, const int_holder &r)
{ return l >= r.int_; }
bool operator< (int i) const
{ return int_ < i; }
bool operator> (int i) const
{ return int_ > i; }
bool operator<= (int i) const
{ return int_ <= i; }
bool operator>= (int i) const
{ return int_ >= i; }
bool operator== (int i) const
{ return int_ == i; }
bool operator!= (int i) const
{ return int_ != i; }
friend std::size_t hash_value(const int_holder &t)
{
boost::hash<int> hasher;
return hasher((&t)->int_value());
}
int int_;
};
template<class ValueType>
struct int_holder_key_of_value
{
typedef int_holder type;
type operator()(const ValueType &tv) const
{ return tv.get_int_holder(); }
};
template<class ValueType>
struct int_priority_of_value
{
typedef int type;
type operator()(const ValueType &tv) const
{ return tv.int_value(); }
};
} //namespace boost{
} //namespace intrusive{
#endif //BOOST_INTRUSIVE_DETAIL_INT_HOLDER_HPP

View File

@@ -0,0 +1,376 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/detail/iterator.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/static_assert.hpp>
namespace boost{ namespace intrusive { namespace test{
//////////////////////////////////////////////
//
// Some traits to avoid special cases with
// containers without bidirectional iterators
//
//////////////////////////////////////////////
template<class C>
struct has_member_reverse_iterator
{
typedef char yes_type;
struct no_type{ char _[2]; };
template<typename D> static no_type test(...);
template<typename D> static yes_type test(typename D::reverse_iterator const*);
static const bool value = sizeof(test<C>(0)) == sizeof(yes_type);
};
template<class C>
struct has_member_const_reverse_iterator
{
typedef char yes_type;
struct no_type{ char _[2]; };
template<typename D> static no_type test(...);
template<typename D> static yes_type test(typename D::const_reverse_iterator const*);
static const bool value = sizeof(test<C>(0)) == sizeof(yes_type);
};
template<class C, bool = has_member_reverse_iterator<C>::value>
struct get_reverse_iterator
{
typedef typename C::reverse_iterator type;
static type begin(C &c) { return c.rbegin(); }
static type end(C &c) { return c.rend(); }
};
template<class C>
struct get_reverse_iterator<C, false>
{
typedef typename C::iterator type;
static type begin(C &c) { return c.begin(); }
static type end(C &c) { return c.end(); }
};
template<class C, bool = has_member_const_reverse_iterator<C>::value>
struct get_const_reverse_iterator
{
typedef typename C::const_reverse_iterator type;
static type begin(C &c) { return c.crbegin(); }
static type end(C &c) { return c.crend(); }
};
template<class C>
struct get_const_reverse_iterator<C, false>
{
typedef typename C::const_iterator type;
static type begin(C &c) { return c.cbegin(); }
static type end(C &c) { return c.cend(); }
};
//////////////////////////////////////////////
//
// Iterator tests
//
//////////////////////////////////////////////
template<class I>
void test_iterator_operations(I b, I e)
{
//Test the range is not empty
BOOST_TEST(b != e);
BOOST_TEST(!(b == e));
{
I i;
I i2(b); //CopyConstructible
i = i2; //Assignable
//Destructible
(void)i;
(void)i2;
}
typedef typename iterator_traits<I>::reference reference;
reference r = *b;
(void)r;
typedef typename iterator_traits<I>::pointer pointer;
pointer p = (iterator_arrow_result)(b);
(void)p;
I &ri= ++b;
(void)ri;
const I &cri= b++;
(void)cri;
}
template<class C>
void test_iterator_compatible(C &c)
{
typedef typename C::iterator iterator;
typedef typename C::const_iterator const_iterator;
typedef typename get_reverse_iterator<C>::type reverse_iterator;
typedef typename get_const_reverse_iterator<C>::type const_reverse_iterator;
//Basic operations
test_iterator_operations(c. begin(), c. end());
test_iterator_operations(c.cbegin(), c.cend());
test_iterator_operations(get_reverse_iterator<C>::begin(c), get_reverse_iterator<C>::end(c));
test_iterator_operations(get_const_reverse_iterator<C>::begin(c), get_const_reverse_iterator<C>::end(c));
//Make sure dangeous conversions are not possible
BOOST_STATIC_ASSERT((!boost::intrusive::detail::is_convertible<const_iterator, iterator>::value));
BOOST_STATIC_ASSERT((!boost::intrusive::detail::is_convertible<const_reverse_iterator, reverse_iterator>::value));
//Test iterator conversions
{
const_iterator ci;
iterator i(c.begin());
ci = i;
(void)ci;
BOOST_ASSERT(ci == i);
BOOST_ASSERT(*ci == *i);
const_iterator ci2(i);
BOOST_ASSERT(ci2 == i);
BOOST_ASSERT(*ci2 == *i);
(void)ci2;
}
//Test reverse_iterator conversions
{
const_reverse_iterator cr;
reverse_iterator r(get_reverse_iterator<C>::begin(c));
cr = r;
BOOST_ASSERT(cr == r);
BOOST_ASSERT(*cr == *r);
const_reverse_iterator cr2(r);
BOOST_ASSERT(cr2 == r);
BOOST_ASSERT(*cr2 == *r);
(void)cr2;
}
}
template<class C>
void test_iterator_input_and_compatible(C &c)
{
typedef typename C::iterator iterator;
typedef typename C::const_iterator const_iterator;
typedef typename get_reverse_iterator<C>::type reverse_iterator;
typedef typename get_const_reverse_iterator<C>::type const_reverse_iterator;
typedef iterator_traits<iterator> nit_traits;
typedef iterator_traits<const_iterator> cit_traits;
typedef iterator_traits<reverse_iterator> rnit_traits;
typedef iterator_traits<const_reverse_iterator> crit_traits;
using boost::move_detail::is_same;
//Trivial typedefs
BOOST_STATIC_ASSERT((!is_same<iterator, const_iterator>::value));
BOOST_STATIC_ASSERT((!is_same<reverse_iterator, const_reverse_iterator>::value));
//difference_type
typedef typename C::difference_type difference_type;
BOOST_STATIC_ASSERT((is_same<difference_type, typename nit_traits::difference_type>::value));
BOOST_STATIC_ASSERT((is_same<difference_type, typename cit_traits::difference_type>::value));
BOOST_STATIC_ASSERT((is_same<difference_type, typename rnit_traits::difference_type>::value));
BOOST_STATIC_ASSERT((is_same<difference_type, typename crit_traits::difference_type>::value));
//value_type
typedef typename C::value_type value_type;
BOOST_STATIC_ASSERT((is_same<value_type, typename nit_traits::value_type>::value));
BOOST_STATIC_ASSERT((is_same<value_type, typename cit_traits::value_type>::value));
BOOST_STATIC_ASSERT((is_same<value_type, typename rnit_traits::value_type>::value));
BOOST_STATIC_ASSERT((is_same<value_type, typename crit_traits::value_type>::value));
//pointer
typedef typename C::pointer pointer;
typedef typename C::const_pointer const_pointer;
BOOST_STATIC_ASSERT((is_same<pointer, typename nit_traits::pointer>::value));
BOOST_STATIC_ASSERT((is_same<const_pointer, typename cit_traits::pointer>::value));
BOOST_STATIC_ASSERT((is_same<pointer, typename rnit_traits::pointer>::value));
BOOST_STATIC_ASSERT((is_same<const_pointer, typename crit_traits::pointer>::value));
//reference
typedef typename C::reference reference;
typedef typename C::const_reference const_reference;
BOOST_STATIC_ASSERT((is_same<reference, typename nit_traits::reference>::value));
BOOST_STATIC_ASSERT((is_same<const_reference, typename cit_traits::reference>::value));
BOOST_STATIC_ASSERT((is_same<reference, typename rnit_traits::reference>::value));
BOOST_STATIC_ASSERT((is_same<const_reference, typename crit_traits::reference>::value));
//Dynamic tests
test_iterator_compatible(c);
}
template<class C, class I>
void test_iterator_forward_functions(C const &c, I const b, I const e)
{
typedef typename C::size_type size_type;
{
size_type i = 0;
I it = b;
for(I it2 = b; i != c.size(); ++it, ++i){
BOOST_TEST(it == it2++);
I ittmp(it);
I *iaddr = &ittmp;
BOOST_TEST(&(++ittmp) == iaddr);
BOOST_TEST(ittmp == it2);
}
BOOST_TEST(i == c.size());
BOOST_TEST(it == e);
}
}
template<class C>
void test_iterator_forward_and_compatible(C &c)
{
test_iterator_input_and_compatible(c);
test_iterator_forward_functions(c, c.begin(), c.end());
test_iterator_forward_functions(c, c.cbegin(), c.cend());
test_iterator_forward_functions(c, get_reverse_iterator<C>::begin(c), get_reverse_iterator<C>::end(c));
test_iterator_forward_functions(c, get_const_reverse_iterator<C>::begin(c), get_const_reverse_iterator<C>::end(c));
}
template<class C, class I>
void test_iterator_bidirectional_functions(C const &c, I const b, I const e)
{
typedef typename C::size_type size_type;
{
size_type i = 0;
I it = e;
for(I it2 = e; i != c.size(); --it, ++i){
BOOST_TEST(it == it2--);
I ittmp(it);
I*iaddr = &ittmp;
BOOST_TEST(&(--ittmp) == iaddr);
BOOST_TEST(ittmp == it2);
BOOST_TEST((++ittmp) == it);
}
BOOST_TEST(i == c.size());
BOOST_TEST(it == b);
}
}
template<class C>
void test_iterator_bidirectional_and_compatible(C &c)
{
test_iterator_forward_and_compatible(c);
test_iterator_bidirectional_functions(c, c.begin(), c.end());
test_iterator_bidirectional_functions(c, c.cbegin(), c.cend());
test_iterator_bidirectional_functions(c, c.rbegin(), c.rend());
test_iterator_bidirectional_functions(c, c.crbegin(), c.crend());
}
template<class C, class I>
void test_iterator_random_functions(C const &c, I const b, I const e)
{
typedef typename C::size_type size_type;
typedef typename C::difference_type difference_type;
{
I it = b;
for(difference_type i = 0, m = difference_type(c.size()); i != m; ++i, ++it){
BOOST_TEST(i == it - b);
BOOST_TEST(b[i] == *it);
BOOST_TEST(&b[i] == &*it);
BOOST_TEST((b + i) == it);
BOOST_TEST((i + b) == it);
BOOST_TEST(b == (it - i));
I tmp(b);
BOOST_TEST((tmp+=i) == it);
tmp = it;
BOOST_TEST(b == (tmp-=i));
}
BOOST_TEST(c.size() == size_type(e - b));
}
{
I it(b), itb(b);
if(b != e){
for(++it; it != e; ++it){
BOOST_TEST(itb < it);
BOOST_TEST(itb <= it);
BOOST_TEST(!(itb > it));
BOOST_TEST(!(itb >= it));
BOOST_TEST(it > itb);
BOOST_TEST(it >= itb);
BOOST_TEST(!(it < itb));
BOOST_TEST(!(it <= itb));
BOOST_TEST(it >= it);
BOOST_TEST(it <= it);
itb = it;
}
}
}
}
template<class C>
void test_iterator_random_and_compatible(C &c)
{
test_iterator_bidirectional_and_compatible(c);
test_iterator_random_functions(c, c.begin(), c.end());
test_iterator_random_functions(c, c.cbegin(), c.cend());
test_iterator_random_functions(c, c.rbegin(), c.rend());
test_iterator_random_functions(c, c.crbegin(), c.crend());
}
////////////////////////
template<class C>
void test_iterator_forward(C &c)
{
typedef typename C::iterator iterator;
typedef typename C::const_iterator const_iterator;
typedef typename get_reverse_iterator<C>::type reverse_iterator;
typedef typename get_const_reverse_iterator<C>::type const_reverse_iterator;
typedef iterator_traits<iterator> nit_traits;
typedef iterator_traits<const_iterator> cit_traits;
typedef iterator_traits<reverse_iterator> rnit_traits;
typedef iterator_traits<const_reverse_iterator> crit_traits;
using boost::intrusive::detail::is_same;
//iterator_category
BOOST_STATIC_ASSERT((is_same<std::forward_iterator_tag, typename nit_traits::iterator_category>::value));
BOOST_STATIC_ASSERT((is_same<std::forward_iterator_tag, typename cit_traits::iterator_category>::value));
BOOST_STATIC_ASSERT((is_same<std::forward_iterator_tag, typename rnit_traits::iterator_category>::value));
BOOST_STATIC_ASSERT((is_same<std::forward_iterator_tag, typename crit_traits::iterator_category>::value));
//Test dynamic
test_iterator_forward_and_compatible(c);
}
template<class C>
void test_iterator_bidirectional(C &c)
{
typedef typename C::iterator iterator;
typedef typename C::const_iterator const_iterator;
typedef typename C::reverse_iterator reverse_iterator;
typedef typename C::const_reverse_iterator const_reverse_iterator;
typedef iterator_traits<iterator> nit_traits;
typedef iterator_traits<const_iterator> cit_traits;
typedef iterator_traits<reverse_iterator> rnit_traits;
typedef iterator_traits<const_reverse_iterator> crit_traits;
using boost::intrusive::detail::is_same;
//iterator_category
BOOST_STATIC_ASSERT((is_same<std::bidirectional_iterator_tag, typename nit_traits::iterator_category>::value));
BOOST_STATIC_ASSERT((is_same<std::bidirectional_iterator_tag, typename cit_traits::iterator_category>::value));
BOOST_STATIC_ASSERT((is_same<std::bidirectional_iterator_tag, typename rnit_traits::iterator_category>::value));
BOOST_STATIC_ASSERT((is_same<std::bidirectional_iterator_tag, typename crit_traits::iterator_category>::value));
//Test dynamic
test_iterator_bidirectional_and_compatible(c);
}
template<class C>
void test_iterator_random(C &c)
{
typedef typename C::iterator iterator;
typedef typename C::const_iterator const_iterator;
typedef typename C::reverse_iterator reverse_iterator;
typedef typename C::const_reverse_iterator const_reverse_iterator;
typedef iterator_traits<iterator> nit_traits;
typedef iterator_traits<const_iterator> cit_traits;
typedef iterator_traits<reverse_iterator> rnit_traits;
typedef iterator_traits<const_reverse_iterator> crit_traits;
using boost::intrusive::detail::is_same;
//iterator_category
BOOST_STATIC_ASSERT((is_same<std::random_access_iterator_tag, typename nit_traits::iterator_category>::value));
BOOST_STATIC_ASSERT((is_same<std::random_access_iterator_tag, typename cit_traits::iterator_category>::value));
BOOST_STATIC_ASSERT((is_same<std::random_access_iterator_tag, typename rnit_traits::iterator_category>::value));
BOOST_STATIC_ASSERT((is_same<std::random_access_iterator_tag, typename crit_traits::iterator_category>::value));
//Test dynamic
test_iterator_random_and_compatible(c);
}
}}} //boost::container::test

View File

@@ -0,0 +1,284 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_ITESTVALUE_HPP
#define BOOST_INTRUSIVE_DETAIL_ITESTVALUE_HPP
#include <iostream>
#include <boost/intrusive/options.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include "nonhook_node.hpp"
#include "int_holder.hpp"
#include <boost/intrusive/detail/get_value_traits.hpp>
#include <boost/container/vector.hpp>
namespace boost{
namespace intrusive{
struct testvalue_filler
{
void *dummy_[3];
};
template<class Hooks>
struct testvalue
: testvalue_filler
, Hooks::base_hook_type
, Hooks::auto_base_hook_type
{
typename Hooks::member_hook_type node_;
typename Hooks::auto_member_hook_type auto_node_;
typename Hooks::nonhook_node_member_type nhn_member_;
int_holder value_;
testvalue()
{}
explicit testvalue(int i)
: value_(i)
{}
testvalue (const testvalue& src)
: value_(src.value_)
{}
// testvalue is used in boost::container::vector and thus prev and next
// have to be handled appropriately when copied:
testvalue & operator= (const testvalue& src)
{
Hooks::base_hook_type::operator=(static_cast<const typename Hooks::base_hook_type&>(src));
Hooks::auto_base_hook_type::operator=(static_cast<const typename Hooks::auto_base_hook_type&>(src));
this->node_ = src.node_;
this->auto_node_ = src.auto_node_;
this->nhn_member_ = src.nhn_member_;
value_ = src.value_;
return *this;
}
void swap_nodes(testvalue &other)
{
Hooks::base_hook_type::swap_nodes(static_cast<typename Hooks::base_hook_type&>(other));
Hooks::auto_base_hook_type::swap_nodes(static_cast<typename Hooks::auto_base_hook_type&>(other));
node_.swap_nodes(other.node_);
auto_node_.swap_nodes(other.auto_node_);
nhn_member_.swap_nodes(other.nhn_member_);
}
bool is_linked() const
{
return Hooks::base_hook_type::is_linked() ||
Hooks::auto_base_hook_type::is_linked() ||
node_.is_linked() ||
auto_node_.is_linked() ||
nhn_member_.is_linked();
}
const int_holder &get_int_holder() const
{ return value_; }
int int_value() const
{ return value_.int_value(); }
~testvalue()
{}
bool operator< (const testvalue &other) const
{ return value_ < other.value_; }
bool operator> (const testvalue &other) const
{ return value_ > other.value_; }
bool operator==(const testvalue &other) const
{ return value_ == other.value_; }
bool operator!=(const testvalue &other) const
{ return value_ != other.value_; }
friend bool operator< (int other1, const testvalue &other2)
{ return other1 < other2.value_.int_; }
friend bool operator> (int other1, const testvalue &other2)
{ return other1 > other2.value_.int_; }
friend bool operator< (const testvalue &other1, int other2)
{ return other1.value_.int_ < other2; }
friend bool operator> (const testvalue &other1, int other2)
{ return other1.value_.int_ > other2; }
friend bool operator== (int other1, const testvalue &other2)
{ return other1 == other2.value_.int_; }
friend bool operator== (const testvalue &other1, int other2)
{ return other1.value_.int_ == other2; }
friend bool operator!= (int other1, const testvalue &other2)
{ return other1 != other2.value_.int_; }
friend bool operator!= (const testvalue &other1, int other2)
{ return other1.value_.int_ != other2; }
friend std::size_t hash_value(const testvalue&t)
{
boost::hash<int> hasher;
return hasher((&t)->int_value());
}
};
template<class T>
std::size_t priority_hash(const T &t)
{ return boost::hash<int>()((&t)->int_value()); }
std::size_t priority_hash(int i)
{ return boost::hash<int>()(i); }
template <class T, class U>
bool priority_order(const T& t1, const U& t2)
{
std::size_t hash1 = (priority_hash)(t1);
boost::hash_combine(hash1, -hash1);
std::size_t hash2 = (priority_hash)(t2);
boost::hash_combine(hash2, -hash2);
return hash1 < hash2;
}
template < typename Node_Algorithms, class Hooks>
void swap_nodes(testvalue<Hooks>& lhs, testvalue<Hooks>& rhs)
{
lhs.swap_nodes(rhs);
}
template<class Hooks>
std::ostream& operator<<
(std::ostream& s, const testvalue<Hooks>& t)
{ return s << t.value_.int_value(); }
struct even_odd
{
template < typename key_type_1, typename key_type_2 >
bool operator()
(const key_type_1& v1
,const key_type_2& v2) const
{
if (((&v1)->int_value() & 1) == ((&v2)->int_value() & 1))
return (&v1)->int_value() < (&v2)->int_value();
else
return (&v2)->int_value() & 1;
}
};
struct is_even
{
template <typename key_type>
bool operator()
(const key_type& v1) const
{ return ((&v1)->int_value() & 1) == 0; }
};
struct is_odd
{
template <typename key_type>
bool operator()
(const key_type& v1) const
{ return ((&v1)->int_value() & 1) != 0; }
};
template <typename>
struct ValueContainer;
template < class Hooks>
struct ValueContainer< testvalue<Hooks> >
{
typedef boost::container::vector< testvalue<Hooks> > type;
};
template < typename Pointer >
class heap_node_holder
{
typedef typename pointer_traits<Pointer>::element_type element_type;
typedef Pointer pointer;
typedef typename pointer_rebind<pointer, const element_type>::type const_pointer;
public:
heap_node_holder()
: m_ptr(pointer_traits<Pointer>::pointer_to(*new element_type))
{}
~heap_node_holder()
{ delete &*m_ptr; }
const_pointer get_node() const
{ return m_ptr; }
pointer get_node()
{ return m_ptr; }
private:
pointer m_ptr;
};
template<class Hooks>
struct testvalue_traits
: public Hooks
{
typedef testvalue< Hooks > value_type;
//base
typedef typename detail::get_base_value_traits
< value_type
, typename Hooks::base_hook_type
>::type base_value_traits;
//auto-base
typedef typename detail::get_base_value_traits
< value_type
, typename Hooks::auto_base_hook_type
>::type auto_base_value_traits;
//member
typedef typename detail::get_member_value_traits
< member_hook
< value_type
, typename Hooks::member_hook_type
, &value_type::node_
>
>::type member_value_traits;
//auto-member
typedef typename detail::get_member_value_traits
< member_hook
< value_type
, typename Hooks::auto_member_hook_type
, &value_type::auto_node_
>
>::type auto_member_value_traits;
//nonmember
typedef nonhook_node_member_value_traits
< value_type
, typename Hooks::nonhook_node_member_type
, &value_type::nhn_member_
, safe_link
> nonhook_value_traits;
};
} //namespace intrusive{
} //namespace boost{
bool priority_order(int t1, int t2)
{
std::size_t hash1 = boost::hash<int>()(t1);
boost::hash_combine(hash1, &t1);
std::size_t hash2 = boost::hash<int>()(t2);
boost::hash_combine(hash2, &t2);
return hash1 < hash2;
}
#endif

View File

@@ -0,0 +1,550 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "common_functors.hpp"
#include <vector>
#include <boost/core/lightweight_test.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
#include <typeinfo>
using namespace boost::intrusive;
template<class VoidPointer>
struct hooks
{
typedef list_base_hook<void_pointer<VoidPointer> > base_hook_type;
typedef list_base_hook< link_mode<auto_unlink>
, void_pointer<VoidPointer>, tag<void> > auto_base_hook_type;
typedef list_member_hook<void_pointer<VoidPointer>, tag<void> > member_hook_type;
typedef list_member_hook< link_mode<auto_unlink>
, void_pointer<VoidPointer> > auto_member_hook_type;
typedef nonhook_node_member< list_node_traits< VoidPointer >,
circular_list_algorithms > nonhook_node_member_type;
};
template < typename ListType, typename ValueContainer >
struct test_list
{
typedef ListType list_type;
typedef typename list_type::value_traits value_traits;
typedef typename value_traits::value_type value_type;
typedef typename list_type::node_algorithms node_algorithms;
static void test_all(ValueContainer&);
static void test_front_back(ValueContainer&);
static void test_sort(ValueContainer&);
static void test_merge(ValueContainer&);
static void test_remove_unique(ValueContainer&);
static void test_insert(ValueContainer&);
static void test_shift(ValueContainer&);
static void test_swap(ValueContainer&);
static void test_clone(ValueContainer&);
static void test_container_from_end(ValueContainer&, detail::true_type);
static void test_container_from_end(ValueContainer&, detail::false_type) {}
};
template < typename ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >::test_all(ValueContainer& values)
{
{
list_type list(values.begin(), values.end());
test::test_container(list);
list.clear();
list.insert(list.end(), values.begin(), values.end());
test::test_sequence_container(list, values);
}
{
list_type list(values.begin(), values.end());
test::test_iterator_bidirectional(list);
}
test_front_back(values);
test_sort(values);
test_merge(values);
test_remove_unique(values);
test_insert(values);
test_shift(values);
test_swap(values);
test_clone(values);
test_container_from_end(values, detail::bool_< ListType::has_container_from_iterator >());
}
//test: push_front, pop_front, push_back, pop_back, front, back, size, empty:
template < class ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >
::test_front_back(ValueContainer& values)
{
list_type testlist;
BOOST_TEST (testlist.empty());
testlist.push_back (values[0]);
BOOST_TEST (testlist.size() == 1);
BOOST_TEST (&testlist.front() == &values[0]);
BOOST_TEST (&testlist.back() == &values[0]);
testlist.push_front (values[1]);
BOOST_TEST (testlist.size() == 2);
BOOST_TEST (&testlist.front() == &values[1]);
BOOST_TEST (&testlist.back() == &values[0]);
testlist.pop_back();
BOOST_TEST (testlist.size() == 1);
const list_type &const_testlist = testlist;
BOOST_TEST (&const_testlist.front() == &values[1]);
BOOST_TEST (&const_testlist.back() == &values[1]);
testlist.pop_front();
BOOST_TEST (testlist.empty());
}
//test: constructor, iterator, reverse_iterator, sort, reverse:
template < class ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >
::test_sort(ValueContainer& values)
{
list_type testlist(values.begin(), values.end());
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
testlist.sort (even_odd());
{ int init_values [] = { 5, 3, 1, 4, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.rbegin() ); }
testlist.reverse();
{ int init_values [] = { 5, 3, 1, 4, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
}
//test: merge due to error in merge implementation:
template < class ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >
::test_remove_unique (ValueContainer& values)
{
{
list_type list(values.begin(), values.end());
list.remove_if(is_even());
int init_values [] = { 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
}
{
list_type list(values.begin(), values.end());
list.remove_if(is_odd());
int init_values [] = { 2, 4 };
TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
}
{
list_type list(values.begin(), values.end());
list.remove_and_dispose_if(is_even(), test::empty_disposer());
int init_values [] = { 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
}
{
list_type list(values.begin(), values.end());
list.remove_and_dispose_if(is_odd(), test::empty_disposer());
int init_values [] = { 2, 4 };
TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
}
{
ValueContainer values2(values);
list_type list(values.begin(), values.end());
list.insert(list.end(), values2.begin(), values2.end());
list.sort();
int init_values [] = { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
list.unique();
int init_values2 [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values2, list.begin() );
}
}
//test: merge due to error in merge implementation:
template < class ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >
::test_merge (ValueContainer& values)
{
list_type testlist1, testlist2;
testlist1.push_front (values[0]);
testlist2.push_front (values[4]);
testlist2.push_front (values[3]);
testlist2.push_front (values[2]);
testlist1.merge (testlist2);
int init_values [] = { 1, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() );
}
//test: assign, insert, const_iterator, const_reverse_iterator, erase, s_iterator_to:
template < class ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >
::test_insert(ValueContainer& values)
{
list_type testlist;
testlist.assign (values.begin() + 2, values.begin() + 5);
const list_type& const_testlist = testlist;
{ int init_values [] = { 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
typename list_type::iterator i = ++testlist.begin();
BOOST_TEST (i->value_ == 4);
{
typename list_type::const_iterator ci = typename list_type::iterator();
(void)ci;
}
testlist.insert (i, values[0]);
{ int init_values [] = { 5, 4, 1, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.rbegin() ); }
i = testlist.iterator_to (values[4]);
BOOST_TEST (&*i == &values[4]);
i = list_type::s_iterator_to (values[4]);
BOOST_TEST (&*i == &values[4]);
typename list_type::const_iterator ic;
ic = testlist.iterator_to (static_cast< typename list_type::const_reference >(values[4]));
BOOST_TEST (&*ic == &values[4]);
ic = list_type::s_iterator_to (static_cast< typename list_type::const_reference >(values[4]));
BOOST_TEST (&*ic == &values[4]);
i = testlist.erase (i);
BOOST_TEST (i == testlist.end());
{ int init_values [] = { 3, 1, 4 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
}
template < class ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >
::test_shift(ValueContainer& values)
{
list_type testlist;
const std::size_t num_values = values.size();
std::vector<int> expected_values(num_values);
for(std::size_t s = 1u; s <= num_values; ++s){
expected_values.resize(s);
//Shift forward all possible positions 3 times
for(std::size_t i = 0u; i < s*3u; ++i){
testlist.insert(testlist.begin(), values.begin(), values.begin() + std::ptrdiff_t(s));
testlist.shift_forward(i);
for(std::size_t j = 0u; j < s; ++j){
expected_values[(j + s - i%s) % s] = int(j + 1u);
}
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin());
testlist.clear();
}
//Shift backwards all possible positions
for(std::size_t i = 0u; i < s*3u; ++i){
testlist.insert(testlist.begin(), values.begin(), values.begin() + std::ptrdiff_t(s));
testlist.shift_backwards(i);
for(std::size_t j = 0u; j < s; ++j){
expected_values[(j + i) % s] = int(j + 1);
}
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin());
testlist.clear();
}
}
}
//test: insert (seq-version), swap, splice, erase (seq-version):
template < class ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >
::test_swap(ValueContainer& values)
{
{ //splice between two lists
list_type testlist1 (values.begin(), values.begin() + 2);
list_type testlist2;
testlist2.insert (testlist2.end(), values.begin() + 2, values.begin() + 5);
testlist1.swap (testlist2);
{ int init_values [] = { 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
{ int init_values [] = { 1, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
testlist2.splice (++testlist2.begin(), testlist1);
{ int init_values [] = { 1, 3, 4, 5, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
BOOST_TEST (testlist1.empty());
testlist1.splice (testlist1.end(), testlist2, ++(++testlist2.begin()));
{ int init_values [] = { 4 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
{ int init_values [] = { 1, 3, 5, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
testlist1.splice (testlist1.end(), testlist2,
testlist2.begin(), ----testlist2.end());
{ int init_values [] = { 4, 1, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
{ int init_values [] = { 5, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
testlist1.erase (testlist1.iterator_to(values[0]), testlist1.end());
BOOST_TEST (testlist1.size() == 1);
BOOST_TEST (&testlist1.front() == &values[3]);
}
{ //splice in the same list
list_type testlist1 (values.begin(), values.begin() + 5);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
//nop 1
testlist1.splice (testlist1.begin(), testlist1, testlist1.begin(), ++testlist1.begin());
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
//nop 2
testlist1.splice (++testlist1.begin(), testlist1, testlist1.begin(), ++testlist1.begin());
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
//nop 3
testlist1.splice (testlist1.begin(), testlist1, ++testlist1.begin(), ++testlist1.begin());
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
testlist1.splice (testlist1.begin(), testlist1, ++testlist1.begin(), ++++testlist1.begin());
{ int init_values [] = { 2, 1, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
testlist1.splice (testlist1.begin(), testlist1, ++testlist1.begin(), ++++++testlist1.begin());
{ int init_values [] = { 1, 3, 2, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
testlist1.splice (++++++++testlist1.begin(), testlist1, testlist1.begin(), ++++testlist1.begin());
{ int init_values [] = { 2, 4, 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
}
{
list_type testlist1 (values.begin(), values.begin() + 2);
list_type testlist2 (values.begin() + 3, values.begin() + 5);
swap_nodes< node_algorithms >(values[0], values[2]);
{ int init_values [] = { 3, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
swap_nodes< node_algorithms >(values[2], values[4]);
{ int init_values [] = { 5, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
{ int init_values [] = { 4, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
}
{
list_type testlist1 (values.begin(), values.begin() + 1);
{ int init_values [] = { 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
swap_nodes< node_algorithms >(values[1], values[2]);
{ int init_values [] = { 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
swap_nodes< node_algorithms >(values[0], values[2]);
{ int init_values [] = { 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
swap_nodes< node_algorithms >(values[0], values[2]);
{ int init_values [] = { 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
}
}
template < class ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >
::test_container_from_end(ValueContainer& values, detail::true_type)
{
list_type testlist1 (values.begin(), values.begin() + std::ptrdiff_t(values.size()));
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.end()));
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.cend()));
}
template < class ListType, typename ValueContainer >
void test_list< ListType, ValueContainer >
::test_clone(ValueContainer& values)
{
list_type testlist1 (values.begin(), values.begin() + std::ptrdiff_t(values.size()));
list_type testlist2;
testlist2.clone_from(testlist1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
BOOST_TEST (testlist2 == testlist1);
testlist2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testlist2.empty());
}
template < typename ValueTraits, bool ConstantTimeSize, bool Default_Holder, typename ValueContainer >
struct make_and_test_list
: test_list< list< typename ValueTraits::value_type,
value_traits< ValueTraits >,
size_type< std::size_t >,
constant_time_size< ConstantTimeSize >
>,
ValueContainer
>
{};
template < typename ValueTraits, bool ConstantTimeSize, typename ValueContainer >
struct make_and_test_list< ValueTraits, ConstantTimeSize, false, ValueContainer >
: test_list< list< typename ValueTraits::value_type,
value_traits< ValueTraits >,
size_type< std::size_t >,
constant_time_size< ConstantTimeSize >,
header_holder_type< heap_node_holder< typename ValueTraits::pointer > >
>,
ValueContainer
>
{};
template < class VoidPointer, bool ConstantTimeSize, bool Default_Holder >
class test_main_template
{
public:
int operator()()
{
typedef testvalue< hooks<VoidPointer> > value_type;
std::vector<value_type> data (5);
for (std::size_t i = 0u; i < 5u; ++i)
data[i].value_ = (int)i + 1;
make_and_test_list < typename detail::get_base_value_traits <
value_type,
typename hooks<VoidPointer>::base_hook_type
>::type,
ConstantTimeSize,
Default_Holder,
std::vector< value_type >
>::test_all(data);
make_and_test_list < typename detail::get_member_value_traits <
member_hook< value_type, typename hooks<VoidPointer>::member_hook_type, &value_type::node_>
>::type,
ConstantTimeSize,
Default_Holder,
std::vector< value_type >
>::test_all(data);
make_and_test_list< nonhook_node_member_value_traits <
value_type,
typename hooks<VoidPointer>::nonhook_node_member_type,
&value_type::nhn_member_,
safe_link
>,
ConstantTimeSize,
Default_Holder,
std::vector< value_type >
>::test_all(data);
return 0;
}
};
template < class VoidPointer, bool Default_Holder >
class test_main_template< VoidPointer, false, Default_Holder >
{
public:
int operator()()
{
typedef testvalue< hooks<VoidPointer> > value_type;
std::vector<value_type> data (5);
for (std::size_t i = 0; i < 5u; ++i)
data[i].value_ = (int)i + 1;
make_and_test_list < typename detail::get_base_value_traits <
value_type,
typename hooks<VoidPointer>::auto_base_hook_type
>::type,
false,
Default_Holder,
std::vector< value_type >
>::test_all(data);
make_and_test_list < typename detail::get_member_value_traits <
member_hook< value_type, typename hooks<VoidPointer>::auto_member_hook_type, &value_type::auto_node_>
>::type,
false,
Default_Holder,
std::vector< value_type >
>::test_all(data);
return 0;
}
};
template < bool ConstantTimeSize >
struct test_main_template_bptr
{
int operator()()
{
typedef BPtr_Value value_type;
typedef BPtr_Value_Traits< List_BPtr_Node_Traits > list_value_traits;
typedef typename list_value_traits::node_ptr node_ptr;
typedef bounded_allocator< value_type > allocator_type;
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
allocator_type allocator;
{
bounded_reference_cont< value_type > ref_cont;
for (std::size_t i = 0; i < 5u; ++i)
{
node_ptr tmp = allocator.allocate(1);
new (tmp.raw()) value_type((int)i + 1);
ref_cont.push_back(*tmp);
}
test_list < list < value_type,
value_traits< list_value_traits >,
size_type< std::size_t >,
constant_time_size< ConstantTimeSize >,
header_holder_type< bounded_pointer_holder< value_type > >
>,
bounded_reference_cont< value_type >
>::test_all(ref_cont);
}
return 0;
}
};
int main()
{
// test (plain/smart pointers) x (nonconst/const size) x (void node allocator)
test_main_template<void*, false, true>()();
test_main_template<boost::intrusive::smart_ptr<void>, false, true>()();
test_main_template<void*, true, true>()();
test_main_template<boost::intrusive::smart_ptr<void>, true, true>()();
// test (bounded pointers) x ((nonconst/const size) x (special node allocator)
test_main_template_bptr< true >()();
test_main_template_bptr< false >()();
return boost::report_errors();
}

View File

@@ -0,0 +1,213 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <boost/intrusive/avl_set.hpp>
#include <boost/intrusive/sg_set.hpp>
#include <boost/intrusive/splay_set.hpp>
#include <boost/intrusive/bs_set.hpp>
#include <boost/intrusive/treap_set.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/static_assert.hpp>
#include "smart_ptr.hpp"
#include <vector>
using namespace boost::intrusive;
struct my_tag;
struct my_tag2;
struct my_tag3;
typedef make_bs_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link>
, tag<my_tag> >::type TreapHook;
typedef make_bs_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link>
, tag<my_tag2> >::type SplayHook;
typedef make_bs_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link>
, tag<my_tag3> >::type BsHook;
class MyClass
: public make_list_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type
, public make_slist_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type
, public make_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type
, public make_unordered_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type
, public make_avl_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type
, public make_bs_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type
, public TreapHook
, public SplayHook
, public BsHook
{
int int_;
public:
MyClass(int i)
: int_(i)
{}
friend bool operator<(const MyClass &l, const MyClass &r)
{ return l.int_ < r.int_; }
friend bool operator==(const MyClass &l, const MyClass &r)
{ return l.int_ == r.int_; }
friend std::size_t hash_value(const MyClass &v)
{ return boost::hash_value(v.int_); }
friend bool priority_order(const MyClass &l, const MyClass &r)
{ return l.int_ < r.int_; }
};
//Define a list that will store MyClass using the public base hook
typedef make_list<MyClass>::type List;
typedef make_slist<MyClass>::type Slist;
typedef make_set<MyClass>::type Set;
typedef make_unordered_set<MyClass>::type USet;
typedef make_avl_set<MyClass>::type AvlSet;
typedef make_sg_set<MyClass>::type SgSet;
typedef make_treap_set<MyClass
, base_hook<TreapHook> >::type TreapSet;
typedef make_splay_set<MyClass
, base_hook<SplayHook> >::type SplaySet;
typedef make_bs_set<MyClass
, base_hook<BsHook> >::type BsSet;
int main()
{
typedef std::vector<MyClass>::iterator VectIt;
typedef std::vector<MyClass>::reverse_iterator VectRit;
//Create several MyClass objects, each one with a different value
std::vector<MyClass> values;
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
USet::bucket_type buckets[100];
List my_list;
Slist my_slist;
Set my_set;
USet my_uset(USet::bucket_traits
(pointer_traits<USet::bucket_ptr>::pointer_to(buckets[0]), 100));
AvlSet my_avlset;
SplaySet my_splayset;
BsSet my_bsset;
SgSet my_sgset;
TreapSet my_treapset;
//Now insert them in containers
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){
my_list.push_front(*it);
my_slist.push_front(*it);
my_set.insert(*it);
my_uset.insert(*it);
my_avlset.insert(*it);
my_splayset.insert(*it);
my_bsset.insert(*it);
my_sgset.insert(*it);
my_treapset.insert(*it);
}
//Now test lists
{
List::const_iterator list_it(my_list.cbegin());
Slist::const_iterator slist_it(my_slist.cbegin());
Set::const_reverse_iterator set_rit(my_set.crbegin());
AvlSet::const_reverse_iterator avlset_rit(my_avlset.crbegin());
SplaySet::const_reverse_iterator splayset_rit(my_splayset.crbegin());
BsSet::const_reverse_iterator bsset_rit(my_bsset.crbegin());
SgSet::const_reverse_iterator sgset_rit(my_sgset.crbegin());
TreapSet::const_reverse_iterator treapset_rit(my_treapset.crbegin());
VectRit vect_it(values.rbegin()), vect_itend(values.rend());
//Test the objects inserted in the base hook list
for( ; vect_it != vect_itend
; ++vect_it, ++list_it, ++slist_it, ++set_rit
, ++avlset_rit, ++splayset_rit, ++bsset_rit, ++sgset_rit, ++treapset_rit
){
if(&*list_it != &*vect_it) return 1;
if(&*slist_it != &*vect_it) return 1;
if(&*set_rit != &*vect_it) return 1;
if(my_uset.find(*set_rit) == my_uset.cend()) return 1;
if(&*avlset_rit != &*vect_it) return 1;
if(&*splayset_rit != &*vect_it) return 1;
if(&*bsset_rit != &*vect_it) return 1;
if(&*sgset_rit != &*vect_it) return 1;
if(&*treapset_rit != &*vect_it) return 1;
}
}
//Check defined types and implicitly defined types are equal
BOOST_STATIC_ASSERT((detail::is_same<make_list_base_hook<void_pointer<void*>, link_mode<safe_link> >::type
,make_list_base_hook<>::type
>::value));
BOOST_STATIC_ASSERT((detail::is_same<make_slist_base_hook<void_pointer<void*>, link_mode<safe_link> >::type
,make_slist_base_hook<>::type
>::value));
BOOST_STATIC_ASSERT((detail::is_same<make_set_base_hook<void_pointer<void*>, link_mode<safe_link> >::type
,make_set_base_hook<>::type
>::value));
BOOST_STATIC_ASSERT((detail::is_same<make_unordered_set_base_hook<void_pointer<void*>, link_mode<safe_link> >::type
,make_unordered_set_base_hook<>::type
>::value));
BOOST_STATIC_ASSERT((detail::is_same<make_avl_set_base_hook<void_pointer<void*>, link_mode<safe_link> >::type
,make_avl_set_base_hook<>::type
>::value));
BOOST_STATIC_ASSERT((detail::is_same<make_bs_set_base_hook<void_pointer<void*>, link_mode<safe_link> >::type
,make_bs_set_base_hook<>::type
>::value));
//Check defined types and implicitly defined types are unequal
BOOST_STATIC_ASSERT(!(detail::is_same<make_list_base_hook<void_pointer<void*>, link_mode<normal_link> >::type
,make_list_base_hook<>::type
>::value));
BOOST_STATIC_ASSERT(!(detail::is_same<make_slist_base_hook<void_pointer<void*>, link_mode<normal_link> >::type
,make_slist_base_hook<>::type
>::value));
BOOST_STATIC_ASSERT(!(detail::is_same<make_set_base_hook<void_pointer<void*>, link_mode<normal_link> >::type
,make_set_base_hook<>::type
>::value));
BOOST_STATIC_ASSERT(!(detail::is_same<make_unordered_set_base_hook<void_pointer<void*>, link_mode<normal_link> >::type
,make_unordered_set_base_hook<>::type
>::value));
BOOST_STATIC_ASSERT(!(detail::is_same<make_avl_set_base_hook<void_pointer<void*>, link_mode<normal_link> >::type
,make_avl_set_base_hook<>::type
>::value));
BOOST_STATIC_ASSERT(!(detail::is_same<make_bs_set_base_hook<void_pointer<void*>, link_mode<normal_link> >::type
,make_bs_set_base_hook<>::type
>::value));
return 0;
}

View File

@@ -0,0 +1,155 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2015.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/set.hpp>
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "rb_test_common.hpp"
#include "generic_multiset_test.hpp"
using namespace boost::intrusive;
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type;
template < class Option1 =void
, class Option2 =void
>
struct container
{
typedef multiset
< typename common_t::value_type
, value_traits<ValueTraits>
, constant_time_size<ConstantTimeSize>
, typename common_t::holder_opt
, typename common_t::key_of_value_opt
, Option1
, Option2
> type;
BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value));
};
};
enum HookType
{
Base,
Member,
NonMember
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type>
class test_main_template;
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base>
{
public:
static void execute()
{
typedef testvalue_traits< rb_hooks<VoidPointer> > testval_traits_t;
//base
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::base_value_traits
, typename testval_traits_t::auto_base_value_traits
>::type base_hook_t;
test::test_generic_multiset
< rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member>
{
public:
static void execute()
{
typedef testvalue_traits< rb_hooks<VoidPointer> > testval_traits_t;
//member
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::member_value_traits
, typename testval_traits_t::auto_member_value_traits
>::type member_hook_t;
test::test_generic_multiset
< rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember>
{
public:
static void execute()
{
typedef testvalue_traits< rb_hooks<VoidPointer> > testval_traits_t;
//nonmember
test::test_generic_multiset
< rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template < bool ConstantTimeSize, bool Map >
struct test_main_template_bptr
{
static void execute()
{
typedef BPtr_Value_Traits< RBTree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_multiset
< rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
int main()
{
//Combinations: VoidPointer x ConstantTimeSize x DefaultHolder x Map
//Minimize them selecting different combinations for raw and smart pointers
//Start with ('false', 'false', 'false') in sets and 'false', 'false', 'true' in multisets
//void pointer
test_main_template<void*, false, false, false, Base>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false, Member>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false, Base>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false, Member>::execute();
test_main_template<void*, true, true, true, NonMember>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true, Base>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true, Member>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute();
//test_main_template<smart_ptr<void>, true, true, false>::execute();
//test_main_template<smart_ptr<void>, true, true, true>::execute();
//bounded_ptr (bool ConstantTimeSize, bool Map)
test_main_template_bptr< false, false >::execute();
//test_main_template_bptr< false, true >::execute();
//test_main_template_bptr< true, false >::execute();
test_main_template_bptr< true, true >::execute();
return boost::report_errors();
}

View File

@@ -0,0 +1,121 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Matei David 2014-2014.
// (C) Copyright Ion Gaztanaga 2014-2014.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_NONHOOK_NODE_HPP
#define BOOST_INTRUSIVE_DETAIL_NONHOOK_NODE_HPP
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/parent_from_member.hpp>
#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/static_assert.hpp>
#include <boost/core/lightweight_test.hpp>
namespace boost{
namespace intrusive{
//This node will only be used in safe or auto unlink modes
//so test it's been properly released
template < typename NodeTraits, template <typename> class Node_Algorithms >
struct nonhook_node_member : public NodeTraits::node
{
typedef NodeTraits node_traits;
typedef typename node_traits::node node;
typedef typename node_traits::node_ptr node_ptr;
typedef typename node_traits::const_node_ptr const_node_ptr;
typedef Node_Algorithms< node_traits > node_algorithms;
nonhook_node_member()
{
node_algorithms::init(pointer_traits<node_ptr>::pointer_to(static_cast< node& >(*this)));
}
nonhook_node_member(const nonhook_node_member& rhs)
{
BOOST_TEST(!rhs.is_linked());
node_algorithms::init(pointer_traits<node_ptr>::pointer_to(static_cast< node& >(*this)));
}
nonhook_node_member& operator = (const nonhook_node_member& rhs)
{
BOOST_TEST(!this->is_linked() && !rhs.is_linked());
return *this;
}
~nonhook_node_member()
{
BOOST_TEST(!this->is_linked());
node_algorithms::init(pointer_traits<node_ptr>::pointer_to(static_cast< node& >(*this)));
}
void swap_nodes(nonhook_node_member& other)
{
node_algorithms::swap_nodes(pointer_traits<node_ptr>::pointer_to(static_cast< node& >(*this)),
pointer_traits<node_ptr>::pointer_to(static_cast< node& >(other)));
}
bool is_linked() const
{
return !node_algorithms::unique(pointer_traits<const_node_ptr>::pointer_to(static_cast< const node& >(*this)));
}
};
template < typename T, typename NonHook_Member, NonHook_Member T::* P, link_mode_type Link_Mode >
struct nonhook_node_member_value_traits
{
typedef T value_type;
typedef typename NonHook_Member::node_traits node_traits;
typedef typename node_traits::node node;
typedef typename node_traits::node_ptr node_ptr;
typedef typename node_traits::const_node_ptr const_node_ptr;
typedef typename pointer_traits<node_ptr>::
template rebind_pointer<T>::type pointer;
typedef typename pointer_traits<node_ptr>::
template rebind_pointer<const T>::type const_pointer;
typedef T & reference;
typedef const T & const_reference;
static const link_mode_type link_mode = Link_Mode;
BOOST_STATIC_ASSERT((Link_Mode == safe_link || Link_Mode == auto_unlink));
static node_ptr to_node_ptr(reference value)
{
return pointer_traits<node_ptr>::pointer_to(static_cast<node&>(value.*P));
}
static const_node_ptr to_node_ptr(const_reference value)
{
return pointer_traits<const_node_ptr>::pointer_to(static_cast<const node&>(value.*P));
}
static pointer to_value_ptr(node_ptr n)
{
return pointer_traits<pointer>::pointer_to
(*detail::parent_from_member<T, NonHook_Member>
(static_cast<NonHook_Member*>(boost::movelib::to_raw_pointer(n)), P));
}
static const_pointer to_value_ptr(const_node_ptr n)
{
return pointer_traits<const_pointer>::pointer_to
(*detail::parent_from_member<T, NonHook_Member>
(static_cast<const NonHook_Member*>(boost::movelib::to_raw_pointer(n)), P));
}
};
}
}
#endif

View File

@@ -0,0 +1,95 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/bs_set.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/avl_set.hpp>
#include <boost/intrusive/sg_set.hpp>
#include <boost/intrusive/treap_set.hpp>
#include <boost/intrusive/splay_set.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/aligned_storage.hpp>
#include <boost/static_assert.hpp>
#include <cstring>
#include <new>
using namespace boost::intrusive;
struct Type
: list_base_hook<>
, slist_base_hook<>
, set_base_hook<>
, avl_set_base_hook<>
, bs_set_base_hook<>
{};
typedef boost::aligned_storage<sizeof(void*)*4>::type buffer_t;
static buffer_t buffer_0x00;
static buffer_t buffer_0xFF;
template<class Iterator>
const Iterator &on_0x00_buffer()
{
BOOST_STATIC_ASSERT(sizeof(buffer_t) >= sizeof(Iterator));
return * ::new(std::memset(&buffer_0x00, 0x00, sizeof(buffer_0x00))) Iterator();
}
template<class Iterator>
const Iterator &on_0xFF_buffer()
{
BOOST_STATIC_ASSERT(sizeof(buffer_t) >= sizeof(Iterator));
return * ::new(std::memset(&buffer_0xFF, 0xFF, sizeof(buffer_0xFF))) Iterator();
}
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reverse_iterator)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_reverse_iterator)
template<class Container>
void check_null_iterators()
{
typedef typename Container::iterator iterator;
typedef typename Container::const_iterator const_iterator;
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
(::, Container
,reverse_iterator, iterator) reverse_iterator;
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
(::, Container
,const_reverse_iterator, const_iterator) const_reverse_iterator;
BOOST_TEST(on_0xFF_buffer<iterator>() == on_0x00_buffer<iterator>());
BOOST_TEST(on_0xFF_buffer<const_iterator>() == on_0x00_buffer<const_iterator>());
BOOST_TEST(on_0xFF_buffer<reverse_iterator>() == on_0x00_buffer<reverse_iterator>());
BOOST_TEST(on_0xFF_buffer<const_reverse_iterator>() == on_0x00_buffer<const_reverse_iterator>());
}
int main()
{
check_null_iterators< list<Type> >();
check_null_iterators< slist<Type> >();
check_null_iterators< bs_set<Type> >();
check_null_iterators< set<Type> >();
check_null_iterators< multiset<Type> >();
check_null_iterators< avl_set<Type> >();
check_null_iterators< avl_multiset<Type> >();
check_null_iterators< sg_set<Type> >();
check_null_iterators< sg_multiset<Type> >();
check_null_iterators< treap_set<Type> >();
check_null_iterators< treap_multiset<Type> >();
check_null_iterators< splay_set<Type> >();
check_null_iterators< splay_multiset<Type> >();
return boost::report_errors();
}

View File

@@ -0,0 +1,55 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/pack_options.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/static_assert.hpp>
struct empty_default{};
using namespace boost::intrusive;
//Test BOOST_INTRUSIVE_OPTION_CONSTANT
BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, is_incremental)
const bool is_incremental_value = pack_options< empty_default, incremental<true> >::type::is_incremental;
BOOST_STATIC_ASSERT(( is_incremental_value == true ));
//Test BOOST_INTRUSIVE_OPTION_TYPE
BOOST_INTRUSIVE_OPTION_TYPE(my_pointer, VoidPointer, typename boost::intrusive::detail::remove_pointer<VoidPointer>::type, my_pointer_type)
typedef pack_options< empty_default, my_pointer<void*> >::type::my_pointer_type my_pointer_type;
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<my_pointer_type, void>::value ));
//test combination of BOOST_INTRUSIVE_OPTION_CONSTANT and BOOST_INTRUSIVE_OPTION_TYPE
// First add new options
struct default_options
{
static const long long_constant = -3;
typedef double * double_typedef;
};
BOOST_INTRUSIVE_OPTION_CONSTANT(incremental2, bool, Enabled, is_incremental2)
BOOST_INTRUSIVE_OPTION_TYPE(my_pointer2, VoidPointer, typename boost::intrusive::detail::add_pointer<VoidPointer>::type, my_pointer_type2)
typedef pack_options < default_options
, incremental<false>
, my_pointer<float*>
, incremental2<true>
, my_pointer2<const char*>
>::type combined_type;
BOOST_STATIC_ASSERT(( combined_type::is_incremental == false ));
BOOST_STATIC_ASSERT(( combined_type::is_incremental2 == true ));
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<combined_type::my_pointer_type, float >::value ));
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<combined_type::my_pointer_type2, const char**>::value ));
//test packing the default options leads to a default options type
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<pack_options<default_options>::type, default_options>::value ));
int main()
{
return 0;
}

View File

@@ -0,0 +1,172 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/parent_from_member.hpp>
#include <boost/core/lightweight_test.hpp>
struct POD
{
int int_;
float float_;
}pod;
struct Derived
: public POD
{
int derived_int_;
float derived_float_;
}derived;
struct Abstract
{
int abstract_int_;
float abstract_float_;
virtual void virtual_func1() = 0;
virtual void virtual_func2() = 0;
virtual ~Abstract(){}
};
struct DerivedPoly
: public Abstract
{
int derivedpoly_int_;
float derivedpoly_float_;
virtual void virtual_func1() BOOST_OVERRIDE {}
virtual void virtual_func2() BOOST_OVERRIDE {}
Abstract *abstract() { return this; }
Abstract const *abstract() const { return this; }
} derivedpoly;
struct MultiInheritance
: public Derived, public DerivedPoly
{
int multiinheritance_int_;
float multiinheritance_float_;
} multiinheritance;
struct Abstract2
{
int abstract2_int_;
float abstract2_float_;
virtual void virtual_func1() = 0;
virtual void virtual_func2() = 0;
virtual ~Abstract2(){}
};
struct DerivedPoly2
: public Abstract2
{
int derivedpoly2_int_;
float derivedpoly2_float_;
virtual void virtual_func1() BOOST_OVERRIDE {}
virtual void virtual_func2() BOOST_OVERRIDE {}
Abstract2 *abstract2() { return this; }
Abstract2 const *abstract2() const { return this; }
virtual ~DerivedPoly2(){}
} derivedpoly2;
struct MultiInheritance2
: public DerivedPoly, public DerivedPoly2
{
int multiinheritance2_int_;
float multiinheritance2_float_;
} multiinheritance2;
struct VirtualDerivedPoly
: public virtual Derived
{
int virtualderivedpoly_int_;
float virtualderivedpoly_float_;
virtual void f1(){}
virtual void f2(){}
virtual ~VirtualDerivedPoly(){}
} virtualderivedpoly;
struct VirtualMultipleDerivedPoly
: public virtual Derived, virtual public DerivedPoly
{
int virtualmultiplederivedpoly_int_;
float virtualmultiplederivedpoly_float_;
virtual void f1(){}
virtual void f2(){}
virtual ~VirtualMultipleDerivedPoly(){}
} virtualmultiplederivedpoly;
struct VirtualDerived
: public virtual Derived
{
int virtualderived_int_;
float virtualderived_float_;
virtual void f1(){}
virtual void f2(){}
virtual ~VirtualDerived(){}
} virtualderived;
using namespace boost::intrusive;
//Add new test with https://svn.boost.org/trac/boost/attachment/ticket/8512/Source1.cpp
int main()
{
//POD
BOOST_TEST(&pod == get_parent_from_member(&pod.int_, &POD::int_));
BOOST_TEST(&pod == get_parent_from_member(&pod.float_, &POD::float_));
//Derived
BOOST_TEST(&derived == get_parent_from_member(&derived.int_, &Derived::int_));
BOOST_TEST(&derived == get_parent_from_member(&derived.float_, &Derived::float_));
BOOST_TEST(&derived == get_parent_from_member(&derived.derived_int_, &Derived::derived_int_));
BOOST_TEST(&derived == get_parent_from_member(&derived.derived_float_, &Derived::derived_float_));
//Abstract
BOOST_TEST(derivedpoly.abstract() == get_parent_from_member(&derivedpoly.abstract_int_, &Abstract::abstract_int_));
BOOST_TEST(derivedpoly.abstract() == get_parent_from_member(&derivedpoly.abstract_float_, &Abstract::abstract_float_));
//DerivedPoly
BOOST_TEST(&derivedpoly == get_parent_from_member(&derivedpoly.abstract_int_, &DerivedPoly::abstract_int_));
BOOST_TEST(&derivedpoly == get_parent_from_member(&derivedpoly.abstract_float_, &DerivedPoly::abstract_float_));
BOOST_TEST(&derivedpoly == get_parent_from_member(&derivedpoly.derivedpoly_int_, &DerivedPoly::derivedpoly_int_));
BOOST_TEST(&derivedpoly == get_parent_from_member(&derivedpoly.derivedpoly_float_, &DerivedPoly::derivedpoly_float_));
//MultiInheritance
BOOST_TEST(multiinheritance.abstract() == get_parent_from_member(&multiinheritance.abstract_int_, &MultiInheritance::abstract_int_));
BOOST_TEST(multiinheritance.abstract() == get_parent_from_member(&multiinheritance.abstract_float_, &MultiInheritance::abstract_float_));
BOOST_TEST(&multiinheritance == get_parent_from_member(&multiinheritance.derivedpoly_int_, &MultiInheritance::derivedpoly_int_));
BOOST_TEST(&multiinheritance == get_parent_from_member(&multiinheritance.derivedpoly_float_, &MultiInheritance::derivedpoly_float_));
BOOST_TEST(&multiinheritance == get_parent_from_member(&multiinheritance.int_, &MultiInheritance::int_));
BOOST_TEST(&multiinheritance == get_parent_from_member(&multiinheritance.float_, &MultiInheritance::float_));
BOOST_TEST(&multiinheritance == get_parent_from_member(&multiinheritance.derived_int_, &MultiInheritance::derived_int_));
BOOST_TEST(&multiinheritance == get_parent_from_member(&multiinheritance.derived_float_, &MultiInheritance::derived_float_));
BOOST_TEST(multiinheritance.abstract() == get_parent_from_member(&multiinheritance.abstract_int_, &MultiInheritance::abstract_int_));
BOOST_TEST(multiinheritance.abstract() == get_parent_from_member(&multiinheritance.abstract_float_, &MultiInheritance::abstract_float_));
BOOST_TEST(&multiinheritance == get_parent_from_member(&multiinheritance.derivedpoly_int_, &MultiInheritance::derivedpoly_int_));
BOOST_TEST(&multiinheritance == get_parent_from_member(&multiinheritance.derivedpoly_float_, &MultiInheritance::derivedpoly_float_));
BOOST_TEST(multiinheritance2.abstract2() == get_parent_from_member(&multiinheritance2.abstract2_int_, &MultiInheritance2::abstract2_int_));
BOOST_TEST(multiinheritance2.abstract2() == get_parent_from_member(&multiinheritance2.abstract2_float_, &MultiInheritance2::abstract2_float_));
BOOST_TEST(&multiinheritance2 == get_parent_from_member(&multiinheritance2.derivedpoly2_int_, &MultiInheritance2::derivedpoly2_int_));
BOOST_TEST(&multiinheritance2 == get_parent_from_member(&multiinheritance2.derivedpoly2_float_, &MultiInheritance2::derivedpoly2_float_));
//MSVC pointer to member data uses RTTI info even when not crossing virtual base boundaries
#ifndef BOOST_INTRUSIVE_MSVC_ABI_PTR_TO_MEMBER
BOOST_TEST(&virtualderived == get_parent_from_member(&virtualderived.virtualderived_int_, &VirtualDerived::virtualderived_int_));
BOOST_TEST(&virtualderived == get_parent_from_member(&virtualderived.virtualderived_float_, &VirtualDerived::virtualderived_float_));
BOOST_TEST(&virtualderivedpoly == get_parent_from_member(&virtualderivedpoly.virtualderivedpoly_int_, &VirtualDerivedPoly::virtualderivedpoly_int_));
BOOST_TEST(&virtualderivedpoly == get_parent_from_member(&virtualderivedpoly.virtualderivedpoly_float_, &VirtualDerivedPoly::virtualderivedpoly_float_));
BOOST_TEST(&virtualmultiplederivedpoly == get_parent_from_member(&virtualmultiplederivedpoly.virtualmultiplederivedpoly_float_, &VirtualMultipleDerivedPoly::virtualmultiplederivedpoly_float_));
BOOST_TEST(&virtualmultiplederivedpoly == get_parent_from_member(&virtualmultiplederivedpoly.virtualmultiplederivedpoly_int_, &VirtualMultipleDerivedPoly::virtualmultiplederivedpoly_int_));
BOOST_TEST(&virtualmultiplederivedpoly == get_parent_from_member(&virtualmultiplederivedpoly.derivedpoly_float_, &VirtualMultipleDerivedPoly::derivedpoly_float_));
BOOST_TEST(&virtualmultiplederivedpoly == get_parent_from_member(&virtualmultiplederivedpoly.derivedpoly_int_, &VirtualMultipleDerivedPoly::derivedpoly_int_));
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,223 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/static_assert.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/core/lightweight_test.hpp>
struct CompleteSmartPtrStats
{
static unsigned static_cast_called;
static unsigned dynamic_cast_called;
static unsigned const_cast_called;
static unsigned pointer_to_called;
static void reset_stats()
{
static_cast_called = 0;
dynamic_cast_called = 0;
const_cast_called = 0;
pointer_to_called = 0;
}
};
unsigned CompleteSmartPtrStats::static_cast_called= 0;
unsigned CompleteSmartPtrStats::dynamic_cast_called = 0;
unsigned CompleteSmartPtrStats::const_cast_called = 0;
unsigned CompleteSmartPtrStats::pointer_to_called = 0;
template<class T>
class CompleteSmartPtr
{
template <class U>
friend class CompleteSmartPtr;
void unspecified_bool_type_func() const {}
typedef void (CompleteSmartPtr::*unspecified_bool_type)() const;
public:
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <class U> using rebind = CompleteSmartPtr<U>;
#else
template <class U> struct rebind
{ typedef CompleteSmartPtr<U> other; };
#endif
typedef char difference_type;
typedef T element_type;
CompleteSmartPtr()
: ptr_(0)
{}
explicit CompleteSmartPtr(T &p)
: ptr_(&p)
{}
CompleteSmartPtr(const CompleteSmartPtr &c)
{ this->ptr_ = c.ptr_; }
CompleteSmartPtr & operator=(const CompleteSmartPtr &c)
{ this->ptr_ = c.ptr_; }
static CompleteSmartPtr pointer_to(T &r)
{ ++CompleteSmartPtrStats::pointer_to_called; return CompleteSmartPtr(r); }
T * operator->() const
{ return ptr_; }
T & operator *() const
{ return *ptr_; }
operator unspecified_bool_type() const
{ return ptr_? &CompleteSmartPtr::unspecified_bool_type_func : 0; }
template<class U>
static CompleteSmartPtr static_cast_from(const CompleteSmartPtr<U> &uptr)
{
++CompleteSmartPtrStats::static_cast_called;
element_type* const p = static_cast<element_type*>(uptr.ptr_);
return p ? CompleteSmartPtr(*p) : CompleteSmartPtr();
}
template<class U>
static CompleteSmartPtr const_cast_from(const CompleteSmartPtr<U> &uptr)
{
++CompleteSmartPtrStats::const_cast_called;
element_type* const p = const_cast<element_type*>(uptr.ptr_);
return p ? CompleteSmartPtr(*p) : CompleteSmartPtr();
}
template<class U>
static CompleteSmartPtr dynamic_cast_from(const CompleteSmartPtr<U> &uptr)
{
++CompleteSmartPtrStats::dynamic_cast_called;
element_type* const p = dynamic_cast<element_type*>(uptr.ptr_);
return p ? CompleteSmartPtr(*p) : CompleteSmartPtr();
}
friend bool operator ==(const CompleteSmartPtr &l, const CompleteSmartPtr &r)
{ return l.ptr_ == r.ptr_; }
friend bool operator !=(const CompleteSmartPtr &l, const CompleteSmartPtr &r)
{ return l.ptr_ != r.ptr_; }
private:
T *ptr_;
};
template<class T>
class SimpleSmartPtr
{
void unspecified_bool_type_func() const {}
typedef void (SimpleSmartPtr::*unspecified_bool_type)() const;
public:
SimpleSmartPtr()
: ptr_(0)
{}
explicit SimpleSmartPtr(T *p)
: ptr_(p)
{}
SimpleSmartPtr(const SimpleSmartPtr &c)
{ this->ptr_ = c.ptr_; }
SimpleSmartPtr & operator=(const SimpleSmartPtr &c)
{ this->ptr_ = c.ptr_; }
friend bool operator ==(const SimpleSmartPtr &l, const SimpleSmartPtr &r)
{ return l.ptr_ == r.ptr_; }
friend bool operator !=(const SimpleSmartPtr &l, const SimpleSmartPtr &r)
{ return l.ptr_ != r.ptr_; }
T* operator->() const
{ return ptr_; }
T & operator *() const
{ return *ptr_; }
operator unspecified_bool_type() const
{ return ptr_? &SimpleSmartPtr::unspecified_bool_type_func : 0; }
private:
T *ptr_;
};
class B{ public: virtual ~B(){} };
class D : public B {};
class DD : public virtual B {};
int main()
{
int dummy;
//Raw pointer
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
<int*>::element_type, int>::value ));
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
<int*>::pointer, int*>::value ));
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
<int*>::difference_type, std::ptrdiff_t>::value ));
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
<int*>::rebind_pointer<double>::type
, double*>::value ));
BOOST_TEST(boost::intrusive::pointer_traits<int*>::pointer_to(dummy) == &dummy);
BOOST_TEST(boost::intrusive::pointer_traits<D*>:: static_cast_from((B*)0) == 0);
BOOST_TEST(boost::intrusive::pointer_traits<D*>:: const_cast_from((const D*)0) == 0);
BOOST_TEST(boost::intrusive::pointer_traits<DD*>:: dynamic_cast_from((B*)0) == 0);
//Complete smart pointer
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
< CompleteSmartPtr<int> >::element_type, int>::value ));
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
< CompleteSmartPtr<int> >::pointer, CompleteSmartPtr<int> >::value ));
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
< CompleteSmartPtr<int> >::difference_type, char>::value ));
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
< CompleteSmartPtr<int> >::rebind_pointer<double>::type
, CompleteSmartPtr<double> >::value ));
//pointer_to
CompleteSmartPtrStats::reset_stats();
BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr<int> >::pointer_to(dummy) == CompleteSmartPtr<int>(dummy));
BOOST_TEST(CompleteSmartPtrStats::pointer_to_called == 1);
//static_cast_from
CompleteSmartPtrStats::reset_stats();
BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr<D> >::static_cast_from(CompleteSmartPtr<B>()) == CompleteSmartPtr<D>());
BOOST_TEST(CompleteSmartPtrStats::static_cast_called == 1);
//const_cast_from
CompleteSmartPtrStats::reset_stats();
BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr<D> >::const_cast_from(CompleteSmartPtr<const D>()) == CompleteSmartPtr<D>());
BOOST_TEST(CompleteSmartPtrStats::const_cast_called == 1);
//dynamic_cast_from
CompleteSmartPtrStats::reset_stats();
BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr<DD> >::dynamic_cast_from(CompleteSmartPtr<B>()) == CompleteSmartPtr<DD>());
BOOST_TEST(CompleteSmartPtrStats::dynamic_cast_called == 1);
//Simple smart pointer
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
< SimpleSmartPtr<int> >::element_type, int>::value ));
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
< SimpleSmartPtr<int> >::pointer, SimpleSmartPtr<int> >::value ));
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
< SimpleSmartPtr<int> >::difference_type, std::ptrdiff_t>::value ));
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
< SimpleSmartPtr<int> >::rebind_pointer<double>::type
, SimpleSmartPtr<double> >::value ));
BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr<int> >::pointer_to(dummy) == SimpleSmartPtr<int>(&dummy));
BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr<D> > ::static_cast_from(SimpleSmartPtr<B>()) == SimpleSmartPtr<D>());
BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr<D> > ::const_cast_from(SimpleSmartPtr<const D>()) == SimpleSmartPtr<D>());
BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr<DD> >::dynamic_cast_from(SimpleSmartPtr<B>()) == SimpleSmartPtr<DD>());
return boost::report_errors();
}

View File

@@ -0,0 +1,45 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_TEST_RB_TEST_COMMON_HPP
#define BOOST_INTRUSIVE_TEST_RB_TEST_COMMON_HPP
#include <boost/intrusive/set_hook.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include "bs_test_common.hpp"
namespace boost {
namespace intrusive {
template<class VoidPointer>
struct rb_hooks
{
typedef set_base_hook<void_pointer<VoidPointer> > base_hook_type;
typedef set_base_hook
<link_mode<auto_unlink>
, void_pointer<VoidPointer>
, tag<void>
, optimize_size<true> > auto_base_hook_type;
typedef set_member_hook
<void_pointer<VoidPointer>
, optimize_size<true> > member_hook_type;
typedef set_member_hook
< link_mode<auto_unlink>
, void_pointer<VoidPointer> > auto_member_hook_type;
typedef nonhook_node_member< rbtree_node_traits<VoidPointer>,
rbtree_algorithms
> nonhook_node_member_type;
};
} //namespace intrusive {
} //namespace boost {
#endif //BOOST_INTRUSIVE_TEST_RB_TEST_COMMON_HPP

View File

@@ -0,0 +1,71 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <boost/intrusive/avl_set.hpp>
#include <boost/intrusive/sg_set.hpp>
#include <boost/intrusive/splay_set.hpp>
#include <boost/intrusive/treap_set.hpp>
#include <cassert>
using namespace boost::intrusive;
typedef list_base_hook<> ListBaseHook;
typedef slist_base_hook<> SListBaseHook;
typedef set_base_hook<> SetBaseHook;
typedef unordered_set_base_hook<> USetBaseHook;
class Foo;
typedef unordered_set<Foo, base_hook<USetBaseHook> > USet;
class Foo : public ListBaseHook, public SListBaseHook, public SetBaseHook, public USetBaseHook
{
USet::bucket_type buckets[1];
Foo(const Foo &);
Foo & operator=(const Foo &);
public:
Foo() : uset_children(USet::bucket_traits(buckets, 1))
{}
list <Foo, base_hook<ListBaseHook> > list_children;
slist<Foo, base_hook<SListBaseHook> > slist_children;
set <Foo, base_hook<SetBaseHook> > set_children;
USet uset_children;
};
void instantiate()
{
list< Foo, base_hook<ListBaseHook> > list_; list_.clear();
slist< Foo, base_hook<SListBaseHook> > slist_; slist_.clear();
set< Foo, base_hook<SetBaseHook> > set_; set_.clear();
USet::bucket_type buckets[1];
USet unordered_set_(USet::bucket_traits(buckets, 1)); unordered_set_.clear();
}
int main()
{
instantiate();
//A small test with list
{
Foo f, f2;
list< Foo, base_hook<ListBaseHook> > l;
l.insert(l.begin(), f);
l.begin()->list_children.insert(l.begin()->list_children.begin(), f2);
assert(l.size() == l.begin()->list_children.size());
l.begin()->list_children.clear();
l.clear();
}
return 0;
}

View File

@@ -0,0 +1,314 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2013-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <boost/intrusive/avl_set.hpp>
#include <boost/intrusive/sg_set.hpp>
#include <boost/intrusive/bs_set.hpp>
#include <boost/intrusive/splay_set.hpp>
#include <boost/intrusive/treap_set.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/static_assert.hpp>
#include "smart_ptr.hpp"
#include <functional> //std::greater/std::less
using namespace boost::intrusive;
struct my_tag;
template<class VoidPtr = void*, link_mode_type mode = normal_link>
class MyClass
: public make_list_base_hook
< void_pointer<VoidPtr>, link_mode<mode> >::type
, public make_slist_base_hook
< void_pointer<VoidPtr>, link_mode<mode> >::type
, public make_set_base_hook
< void_pointer<VoidPtr>, link_mode<mode> >::type
, public make_unordered_set_base_hook
< void_pointer<VoidPtr>, link_mode<mode> >::type
, public make_avl_set_base_hook
< void_pointer<VoidPtr>, link_mode<mode> >::type
, public make_bs_set_base_hook
< void_pointer<VoidPtr>, link_mode<mode> >::type
{
int int_;
public:
MyClass(int i)
: int_(i)
{}
friend bool operator<(const MyClass &l, const MyClass &r)
{ return l.int_ < r.int_; }
friend bool operator==(const MyClass &l, const MyClass &r)
{ return l.int_ == r.int_; }
friend std::size_t hash_value(const MyClass &v)
{ return boost::hash_value(v.int_); }
friend bool priority_order(const MyClass &l, const MyClass &r)
{ return l.int_ < r.int_; }
};
template<class T>
struct inverse_priority
{
bool operator()(const T &l, const T &r)
{ return l.int_ > r.int_; }
};
template<class T>
struct inverse_hash
{
bool operator()(const T &l)
{ return hash_value(l); }
};
template<class T>
struct alternative_equal
{
bool operator()(const T &l, const T &r)
{ return l.int_ == r.int_; }
};
int main()
{
////////////
// list
////////////
BOOST_STATIC_ASSERT((!detail::is_same< list<MyClass<> >::iterator
, list<MyClass<> >::const_iterator
>::value));
//constant_time_size does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< list<MyClass<>, constant_time_size<true> >::iterator
, list<MyClass<>, constant_time_size<false> >::iterator
>::value));
//void_pointer does change iterator
BOOST_STATIC_ASSERT((!detail::is_same< list<MyClass<> >::iterator
, list<MyClass<smart_ptr<void> > >::iterator
>::value));
//size_type does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< list<MyClass<>, size_type<unsigned int > >::iterator
, list<MyClass<>, size_type<unsigned char> >::iterator
>::value));
////////////
// slist
////////////
BOOST_STATIC_ASSERT((!detail::is_same< slist<MyClass<> >::iterator
, slist<MyClass<> >::const_iterator
>::value));
//constant_time_size does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< slist<MyClass<>, constant_time_size<true> >::iterator
, slist<MyClass<>, constant_time_size<false> >::iterator
>::value));
//void_pointer does change iterator
BOOST_STATIC_ASSERT((!detail::is_same< slist<MyClass<> >::iterator
, slist<MyClass<smart_ptr<void> > >::iterator
>::value));
//size_type does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< slist<MyClass<>, size_type<unsigned int > >::iterator
, slist<MyClass<>, size_type<unsigned char> >::iterator
>::value));
//cache_last does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< slist<MyClass<>, cache_last<false> >::iterator
, slist<MyClass<>, cache_last<true> >::iterator
>::value));
//linear does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< slist<MyClass<>, linear<false> >::iterator
, slist<MyClass<>, linear<true> >::iterator
>::value));
////////////
// set
////////////
BOOST_STATIC_ASSERT((!detail::is_same< set<MyClass<> >::iterator
, set<MyClass<> >::const_iterator
>::value));
//constant_time_size does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< set<MyClass<>, constant_time_size<true> >::iterator
, set<MyClass<>, constant_time_size<false> >::iterator
>::value));
//void_pointer does change iterator
BOOST_STATIC_ASSERT((!detail::is_same< set<MyClass<> >::iterator
, set<MyClass<smart_ptr<void> > >::iterator
>::value));
//size_type does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< set<MyClass<>, size_type<unsigned int > >::iterator
, set<MyClass<>, size_type<unsigned char> >::iterator
>::value));
//compare does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< set<MyClass<>, compare< std::greater<MyClass<> > > >::iterator
, set<MyClass<>, compare< std::less<MyClass<> > > >::iterator
>::value));
////////////
// avl_set
////////////
BOOST_STATIC_ASSERT((!detail::is_same< avl_set<MyClass<> >::iterator
, avl_set<MyClass<> >::const_iterator
>::value));
//constant_time_size does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< avl_set<MyClass<>, constant_time_size<true> >::iterator
, avl_set<MyClass<>, constant_time_size<false> >::iterator
>::value));
//void_pointer does change iterator
BOOST_STATIC_ASSERT((!detail::is_same< avl_set<MyClass<> >::iterator
, avl_set<MyClass<smart_ptr<void> > >::iterator
>::value));
//size_type does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< avl_set<MyClass<>, size_type<unsigned int > >::iterator
, avl_set<MyClass<>, size_type<unsigned char> >::iterator
>::value));
//compare does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< avl_set<MyClass<>, compare< std::greater<MyClass<> > > >::iterator
, avl_set<MyClass<>, compare< std::less<MyClass<> > > >::iterator
>::value));
////////////
// sg_set
////////////
BOOST_STATIC_ASSERT((!detail::is_same< sg_set<MyClass<> >::iterator
, sg_set<MyClass<> >::const_iterator
>::value));
//void_pointer does change iterator
BOOST_STATIC_ASSERT((!detail::is_same< sg_set<MyClass<> >::iterator
, sg_set<MyClass<smart_ptr<void> > >::iterator
>::value));
//size_type does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< sg_set<MyClass<>, size_type<unsigned int > >::iterator
, sg_set<MyClass<>, size_type<unsigned char> >::iterator
>::value));
//compare does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< sg_set<MyClass<>, compare< std::greater<MyClass<> > > >::iterator
, sg_set<MyClass<>, compare< std::less<MyClass<> > > >::iterator
>::value));
//floating_point does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< sg_set<MyClass<>, floating_point<false> >::iterator
, sg_set<MyClass<>, floating_point<true> >::iterator
>::value));
////////////
// bs_set
////////////
BOOST_STATIC_ASSERT((!detail::is_same< bs_set<MyClass<> >::iterator
, bs_set<MyClass<> >::const_iterator
>::value));
//constant_time_size does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< bs_set<MyClass<>, constant_time_size<true> >::iterator
, bs_set<MyClass<>, constant_time_size<false> >::iterator
>::value));
//void_pointer does change iterator
BOOST_STATIC_ASSERT((!detail::is_same< bs_set<MyClass<> >::iterator
, bs_set<MyClass<smart_ptr<void> > >::iterator
>::value));
//size_type does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< bs_set<MyClass<>, size_type<unsigned int > >::iterator
, bs_set<MyClass<>, size_type<unsigned char> >::iterator
>::value));
//compare does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< bs_set<MyClass<>, compare< std::greater<MyClass<> > > >::iterator
, bs_set<MyClass<>, compare< std::less<MyClass<> > > >::iterator
>::value));
////////////
// splay_set
////////////
BOOST_STATIC_ASSERT((!detail::is_same< splay_set<MyClass<> >::iterator
, splay_set<MyClass<> >::const_iterator
>::value));
//constant_time_size does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< splay_set<MyClass<>, constant_time_size<true> >::iterator
, splay_set<MyClass<>, constant_time_size<false> >::iterator
>::value));
//void_pointer does change iterator
BOOST_STATIC_ASSERT((!detail::is_same< splay_set<MyClass<> >::iterator
, splay_set<MyClass<smart_ptr<void> > >::iterator
>::value));
//size_type does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< splay_set<MyClass<>, size_type<unsigned int > >::iterator
, splay_set<MyClass<>, size_type<unsigned char> >::iterator
>::value));
//compare does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< splay_set<MyClass<>, compare< std::greater<MyClass<> > > >::iterator
, splay_set<MyClass<>, compare< std::less<MyClass<> > > >::iterator
>::value));
////////////
// treap_set
////////////
BOOST_STATIC_ASSERT((!detail::is_same< treap_set<MyClass<> >::iterator
, treap_set<MyClass<> >::const_iterator
>::value));
//constant_time_size does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< treap_set<MyClass<>, constant_time_size<true> >::iterator
, treap_set<MyClass<>, constant_time_size<false> >::iterator
>::value));
//void_pointer does change iterator
BOOST_STATIC_ASSERT((!detail::is_same< treap_set<MyClass<> >::iterator
, treap_set<MyClass<smart_ptr<void> > >::iterator
>::value));
//size_type does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< treap_set<MyClass<>, size_type<unsigned int > >::iterator
, treap_set<MyClass<>, size_type<unsigned char> >::iterator
>::value));
//compare does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< treap_set<MyClass<>, compare< std::greater<MyClass<> > > >::iterator
, treap_set<MyClass<>, compare< std::less<MyClass<> > > >::iterator
>::value));
//priority does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< treap_set<MyClass<> >::iterator
, treap_set<MyClass<>, priority< inverse_priority<MyClass<> > > >::iterator
>::value));
//////////////
// common tree
//////////////
BOOST_STATIC_ASSERT((detail::is_same< bs_set<MyClass<> >::iterator
, sg_set<MyClass<> >::iterator
>::value));
BOOST_STATIC_ASSERT((detail::is_same< bs_set<MyClass<> >::iterator
, treap_set<MyClass<> >::iterator
>::value));
BOOST_STATIC_ASSERT((detail::is_same< bs_set<MyClass<> >::iterator
, splay_set<MyClass<> >::iterator
>::value));
////////////
// unordered_set
////////////
BOOST_STATIC_ASSERT((!detail::is_same< unordered_set<MyClass<> >::iterator
, unordered_set<MyClass<> >::const_iterator
>::value));
//constant_time_size does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< unordered_set<MyClass<>, constant_time_size<true> >::iterator
, unordered_set<MyClass<>, constant_time_size<false> >::iterator
>::value));
//void_pointer does change iterator
BOOST_STATIC_ASSERT((!detail::is_same< unordered_set<MyClass<> >::iterator
, unordered_set<MyClass<smart_ptr<void> > >::iterator
>::value));
//size_type does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< unordered_set<MyClass<>, size_type<unsigned int > >::iterator
, unordered_set<MyClass<>, size_type<unsigned char> >::iterator
>::value));
//hash does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< unordered_set<MyClass<> >::iterator
, unordered_set<MyClass<>, hash< inverse_hash<MyClass<> > > >::iterator
>::value));
//equal does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< unordered_set<MyClass<> >::iterator
, unordered_set<MyClass<>, equal< alternative_equal<MyClass<> > > >::iterator
>::value));
//power_2_buckets does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< unordered_set<MyClass<> >::iterator
, unordered_set<MyClass<>, power_2_buckets<true> >::iterator
>::value));
//cache_begin does not change iterator
BOOST_STATIC_ASSERT((detail::is_same< unordered_set<MyClass<> >::iterator
, unordered_set<MyClass<>, cache_begin<true> >::iterator
>::value));
return 0;
}

View File

@@ -0,0 +1,156 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2015.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/set.hpp>
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "rb_test_common.hpp"
#include "generic_set_test.hpp"
using namespace boost::intrusive;
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type;
template < class Option1 =void
, class Option2 =void
>
struct container
{
typedef set
< typename common_t::value_type
, value_traits<ValueTraits>
, constant_time_size<ConstantTimeSize>
, typename common_t::holder_opt
, typename common_t::key_of_value_opt
, Option1
, Option2
> type;
BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value));
};
};
enum HookType
{
Base,
Member,
NonMember
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type>
class test_main_template;
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base>
{
public:
static void execute()
{
typedef testvalue_traits< rb_hooks<VoidPointer> > testval_traits_t;
//base
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::base_value_traits
, typename testval_traits_t::auto_base_value_traits
>::type base_hook_t;
test::test_generic_set
< rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member>
{
public:
static void execute()
{
typedef testvalue_traits< rb_hooks<VoidPointer> > testval_traits_t;
//member
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::member_value_traits
, typename testval_traits_t::auto_member_value_traits
>::type member_hook_t;
test::test_generic_set
< rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember>
{
public:
static void execute()
{
typedef testvalue_traits< rb_hooks<VoidPointer> > testval_traits_t;
//nonmember
test::test_generic_set
< rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template < bool ConstantTimeSize, bool Map >
struct test_main_template_bptr
{
static void execute()
{
typedef BPtr_Value_Traits< RBTree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_set
< rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
int main()
{
//Combinations: VoidPointer x ConstantTimeSize x DefaultHolder x Map
//Minimize them selecting different combinations for raw and smart pointers
//Start with ('false', 'false', 'false') in sets and 'false', 'false', 'true' in multisets
//void pointer
test_main_template<void*, false, false, false, Base>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false, Member>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false, Base>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false, Member>::execute();
test_main_template<void*, true, true, true, NonMember>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true, Base>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true, Member>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute();
//test_main_template<smart_ptr<void>, true, true, false>::execute();
//test_main_template<smart_ptr<void>, true, true, true>::execute();
//bounded_ptr (bool ConstantTimeSize, bool Map)
test_main_template_bptr< false, false >::execute();
//test_main_template_bptr< false, true >::execute();
//test_main_template_bptr< true, false >::execute();
test_main_template_bptr< true, true >::execute();
return boost::report_errors();
}

View File

@@ -0,0 +1,148 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/sg_set.hpp>
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "bs_test_common.hpp"
#include "generic_multiset_test.hpp"
using namespace boost::intrusive;
template < class ValueTraits, bool FloatingPoint, bool DefaultHolder, bool Map >
struct rebinder
{
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type;
template < class Option1 =void
, class Option2 =void
>
struct container
{
typedef sg_multiset
< typename common_t::value_type
, value_traits<ValueTraits>
, floating_point<FloatingPoint>
, typename common_t::holder_opt
, typename common_t::key_of_value_opt
, Option1
, Option2
> type;
BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value));
};
};
enum HookType
{
Base,
Member,
NonMember
};
template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map, HookType Type>
class test_main_template;
template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, FloatingPoint, DefaultHolder, Map, Base>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//base
typedef typename testval_traits_t::base_value_traits base_hook_t;
test::test_generic_multiset
< rebinder<base_hook_t, FloatingPoint, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, FloatingPoint, DefaultHolder, Map, Member>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//member
typedef typename testval_traits_t::member_value_traits member_hook_t;
test::test_generic_multiset
< rebinder<member_hook_t, FloatingPoint, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, FloatingPoint, DefaultHolder, Map, NonMember>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//nonmember
test::test_generic_multiset
< rebinder<typename testval_traits_t::nonhook_value_traits, FloatingPoint, DefaultHolder, Map>
>::test_all();
}
};
template < bool FloatingPoint, bool Map >
struct test_main_template_bptr
{
static void execute()
{
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_multiset
< rebinder< value_traits, FloatingPoint, true, Map>
>::test_all();
}
};
int main()
{
//Combinations: VoidPointer x FloatingPoint x DefaultHolder x Map
//Minimize them selecting different combinations for raw and smart pointers
//Start with ('false', 'false', 'false') in sets and 'false', 'false', 'true' in multisets
//void pointer
test_main_template<void*, false, false, false, Base>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false, Member>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false, Base>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false, Member>::execute();
test_main_template<void*, true, true, true, NonMember>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true, Base>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true, Member>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute();
//test_main_template<smart_ptr<void>, true, true, false>::execute();
//test_main_template<smart_ptr<void>, true, true, true>::execute();
//bounded_ptr (bool FloatingPoint, bool Map)
test_main_template_bptr< false, false >::execute();
//test_main_template_bptr< false, true >::execute();
//test_main_template_bptr< true, false >::execute();
test_main_template_bptr< true, true >::execute();
return boost::report_errors();
}

View File

@@ -0,0 +1,147 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/sg_set.hpp>
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "bs_test_common.hpp"
#include "generic_set_test.hpp"
using namespace boost::intrusive;
template < class ValueTraits, bool FloatingPoint, bool DefaultHolder, bool Map >
struct rebinder
{
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type;
template < class Option1 =void
, class Option2 =void
>
struct container
{
typedef sg_set
< typename common_t::value_type
, value_traits<ValueTraits>
, floating_point<FloatingPoint>
, typename common_t::holder_opt
, typename common_t::key_of_value_opt
, Option1
, Option2
> type;
BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value));
};
};
enum HookType
{
Base,
Member,
NonMember
};
template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map, HookType Type>
class test_main_template;
template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, FloatingPoint, DefaultHolder, Map, Base>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//base
typedef typename testval_traits_t::base_value_traits base_hook_t;
test::test_generic_set
< rebinder<base_hook_t, FloatingPoint, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, FloatingPoint, DefaultHolder, Map, Member>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//member
typedef typename testval_traits_t::member_value_traits member_hook_t;
test::test_generic_set
< rebinder<member_hook_t, FloatingPoint, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool FloatingPoint, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, FloatingPoint, DefaultHolder, Map, NonMember>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//nonmember
test::test_generic_set
< rebinder<typename testval_traits_t::nonhook_value_traits, FloatingPoint, DefaultHolder, Map>
>::test_all();
}
};
template < bool FloatingPoint, bool Map >
struct test_main_template_bptr
{
static void execute()
{
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_set
< rebinder< value_traits, FloatingPoint, true, Map>
>::test_all();
}
};
int main()
{
//Combinations: VoidPointer x FloatingPoint x DefaultHolder x Map
//Minimize them selecting different combinations for raw and smart pointers
//Start with ('false', 'false', 'false') in sets and 'false', 'false', 'true' in multisets
//void pointer
test_main_template<void*, false, false, false, Base>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false, Member>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false, Base>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false, Member>::execute();
test_main_template<void*, true, true, true, NonMember>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true, Base>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true, Member>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute();
//test_main_template<smart_ptr<void>, true, true, false>::execute();
//test_main_template<smart_ptr<void>, true, true, true>::execute();
//bounded_ptr (bool FloatingPoint, bool Map)
test_main_template_bptr< false, false >::execute();
//test_main_template_bptr< false, true >::execute();
//test_main_template_bptr< true, false >::execute();
test_main_template_bptr< true, true >::execute();
return boost::report_errors();
}

View File

@@ -0,0 +1,695 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "common_functors.hpp"
#include <vector>
#include <boost/core/lightweight_test.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
#include <typeinfo>
using namespace boost::intrusive;
template<class VoidPointer>
struct hooks
{
typedef slist_base_hook<void_pointer<VoidPointer> > base_hook_type;
typedef slist_base_hook< link_mode<auto_unlink>
, void_pointer<VoidPointer>, tag<void> > auto_base_hook_type;
typedef slist_member_hook<void_pointer<VoidPointer>, tag<void> > member_hook_type;
typedef slist_member_hook< link_mode<auto_unlink>
, void_pointer<VoidPointer> > auto_member_hook_type;
typedef nonhook_node_member< slist_node_traits< VoidPointer >,
circular_slist_algorithms
> nonhook_node_member_type;
};
template < typename ListType, typename ValueContainer >
struct test_slist
{
typedef ListType list_type;
typedef typename list_type::value_traits value_traits;
typedef typename value_traits::value_type value_type;
typedef typename list_type::node_algorithms node_algorithms;
static void test_all(ValueContainer&);
static void test_front(ValueContainer&);
static void test_back(ValueContainer&, detail::true_type);
static void test_back(ValueContainer&, detail::false_type) {}
static void test_sort(ValueContainer&);
static void test_merge(ValueContainer&);
static void test_remove_unique(ValueContainer&);
static void test_insert(ValueContainer&);
static void test_shift(ValueContainer&);
static void test_swap(ValueContainer&);
static void test_slow_insert(ValueContainer&);
static void test_clone(ValueContainer&);
static void test_container_from_end(ValueContainer&, detail::true_type);
static void test_container_from_end(ValueContainer&, detail::false_type) {}
};
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_all (ValueContainer& values)
{
{
list_type list(values.begin(), values.end());
test::test_container(list);
list.clear();
list.insert(list.end(), values.begin(), values.end());
test::test_sequence_container(list, values);
}
{
list_type list(values.begin(), values.end());
test::test_iterator_forward(list);
}
test_front(values);
test_back(values, detail::bool_< list_type::cache_last >());
test_sort(values);
test_merge (values);
test_remove_unique(values);
test_insert(values);
test_shift(values);
test_slow_insert (values);
test_swap(values);
test_clone(values);
test_container_from_end(values, detail::bool_< !list_type::linear && list_type::has_container_from_iterator >());
}
//test: push_front, pop_front, front, size, empty:
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_front(ValueContainer& values)
{
list_type testlist;
BOOST_TEST (testlist.empty());
testlist.push_front (values[0]);
BOOST_TEST (testlist.size() == 1);
BOOST_TEST (&testlist.front() == &values[0]);
testlist.push_front (values[1]);
BOOST_TEST (testlist.size() == 2);
BOOST_TEST (&testlist.front() == &values[1]);
testlist.pop_front();
BOOST_TEST (testlist.size() == 1);
BOOST_TEST (&testlist.front() == &values[0]);
testlist.pop_front();
BOOST_TEST (testlist.empty());
}
//test: push_front, pop_front, front, size, empty:
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_back(ValueContainer& values, detail::true_type)
{
list_type testlist;
BOOST_TEST (testlist.empty());
testlist.push_back (values[0]);
BOOST_TEST (testlist.size() == 1);
BOOST_TEST (&testlist.front() == &values[0]);
BOOST_TEST (&testlist.back() == &values[0]);
testlist.push_back(values[1]);
BOOST_TEST(*testlist.previous(testlist.end()) == values[1]);
BOOST_TEST (&testlist.front() == &values[0]);
BOOST_TEST (&testlist.back() == &values[1]);
}
//test: merge due to error in merge implementation:
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_merge (ValueContainer& values)
{
list_type testlist1, testlist2;
testlist1.push_front (values[0]);
testlist2.push_front (values[4]);
testlist2.push_front (values[3]);
testlist2.push_front (values[2]);
testlist1.merge (testlist2);
int init_values [] = { 1, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() );
}
//test: merge due to error in merge implementation:
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_remove_unique (ValueContainer& values)
{
{
list_type list(values.begin(), values.end());
list.remove_if(is_even());
int init_values [] = { 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
}
{
list_type list(values.begin(), values.end());
list.remove_if(is_odd());
int init_values [] = { 2, 4 };
TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
}
{
list_type list(values.begin(), values.end());
list.remove_and_dispose_if(is_even(), test::empty_disposer());
int init_values [] = { 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
}
{
list_type list(values.begin(), values.end());
list.remove_and_dispose_if(is_odd(), test::empty_disposer());
int init_values [] = { 2, 4 };
TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
}
{
ValueContainer values2(values);
list_type list(values.begin(), values.end());
list.insert_after(list.before_begin(), values2.begin(), values2.end());
list.sort();
int init_values [] = { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
list.unique();
int init_values2 [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values2, list.begin() );
}
}
//test: constructor, iterator, sort, reverse:
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_sort(ValueContainer& values)
{
list_type testlist (values.begin(), values.end());
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
testlist.sort (even_odd());
{ int init_values [] = { 2, 4, 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
testlist.reverse();
{ int init_values [] = { 5, 3, 1, 4, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
}
//test: assign, insert_after, const_iterator, erase_after, s_iterator_to, previous:
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_insert(ValueContainer& values)
{
list_type testlist;
testlist.assign (values.begin() + 2, values.begin() + 5);
const list_type& const_testlist = testlist;
{ int init_values [] = { 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
typename list_type::iterator i = ++testlist.begin();
BOOST_TEST (i->value_ == 4);
testlist.insert_after (i, values[0]);
{ int init_values [] = { 3, 4, 1, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
i = testlist.iterator_to (values[4]);
BOOST_TEST (&*i == &values[4]);
i = list_type::s_iterator_to (values[4]);
BOOST_TEST (&*i == &values[4]);
typename list_type::const_iterator ic;
ic = testlist.iterator_to (static_cast< typename list_type::const_reference >(values[4]));
BOOST_TEST (&*ic == &values[4]);
ic = list_type::s_iterator_to (static_cast< typename list_type::const_reference >(values[4]));
BOOST_TEST (&*ic == &values[4]);
i = testlist.previous (i);
BOOST_TEST (&*i == &values[0]);
testlist.erase_after (i);
BOOST_TEST (&*i == &values[0]);
{ int init_values [] = { 3, 4, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
}
//test: insert, const_iterator, erase, siterator_to:
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_slow_insert (ValueContainer& values)
{
list_type testlist;
testlist.push_front (values[4]);
testlist.insert (testlist.begin(), values.begin() + 2, values.begin() + 4);
const list_type& const_testlist = testlist;
{ int init_values [] = { 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
typename list_type::iterator i = ++testlist.begin();
BOOST_TEST (i->value_ == 4);
testlist.insert (i, values[0]);
{ int init_values [] = { 3, 1, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
i = testlist.iterator_to (values[4]);
BOOST_TEST (&*i == &values[4]);
i = list_type::s_iterator_to (values[4]);
BOOST_TEST (&*i == &values[4]);
i = testlist.erase (i);
BOOST_TEST (i == testlist.end());
{ int init_values [] = { 3, 1, 4 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
testlist.erase (++testlist.begin(), testlist.end());
BOOST_TEST (testlist.size() == 1);
BOOST_TEST (testlist.begin()->value_ == 3);
}
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_shift(ValueContainer& values)
{
list_type testlist;
const std::size_t num_values = values.size();
std::vector<int> expected_values(num_values);
//Shift forward all possible positions 3 times
for(std::size_t s = 1; s <= num_values; ++s){
expected_values.resize(s);
for(std::size_t i = 0; i < s*3u; ++i){
testlist.insert_after(testlist.before_begin(), values.begin(), values.begin() + std::ptrdiff_t(s));
testlist.shift_forward(i);
for(std::size_t j = 0; j < s; ++j){
expected_values[(j + s - i%s) % s] = int(j + 1);
}
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin())
testlist.clear();
}
//Shift backwards all possible positions
for(std::size_t i = 0; i < s*3u; ++i){
testlist.insert_after(testlist.before_begin(), values.begin(), values.begin() + std::ptrdiff_t(s));
testlist.shift_backwards(i);
for(std::size_t j = 0; j < s; ++j){
expected_values[(j + i) % s] = int(j + 1);
}
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin())
testlist.clear();
}
}
}
//test: insert_after (seq-version), swap, splice_after:
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_swap(ValueContainer& values)
{
{
list_type testlist1 (values.begin(), values.begin() + 2);
list_type testlist2;
testlist2.insert_after (testlist2.before_begin(), values.begin() + 2, values.begin() + 5);
testlist1.swap(testlist2);
{ int init_values [] = { 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
{ int init_values [] = { 1, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
testlist2.splice_after (testlist2.begin(), testlist1);
{ int init_values [] = { 1, 3, 4, 5, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
BOOST_TEST (testlist1.empty());
testlist1.splice_after (testlist1.before_begin(), testlist2, ++testlist2.begin());
{ int init_values [] = { 4 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
{ int init_values [] = { 1, 3, 5, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
testlist1.splice_after (testlist1.begin(), testlist2,
testlist2.before_begin(), ++++testlist2.begin());
{ int init_values [] = { 4, 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
{ int init_values [] = { 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
}
{ //splice in the same list
list_type testlist1 (values.begin(), values.begin() + 5);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
//nop 1
testlist1.splice_after (testlist1.before_begin(), testlist1, testlist1.before_begin(), ++testlist1.before_begin());
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
//nop 2
testlist1.splice_after (++testlist1.before_begin(), testlist1, testlist1.before_begin(), ++testlist1.before_begin());
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
//nop 3
testlist1.splice_after (testlist1.before_begin(), testlist1, ++testlist1.before_begin(), ++testlist1.before_begin());
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
testlist1.splice_after (testlist1.before_begin(), testlist1, ++testlist1.before_begin(), ++++testlist1.before_begin());
{ int init_values [] = { 2, 1, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
testlist1.splice_after (testlist1.before_begin(), testlist1, ++testlist1.before_begin(), ++++++testlist1.before_begin());
{ int init_values [] = { 1, 3, 2, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
testlist1.splice_after (++++++++testlist1.before_begin(), testlist1, testlist1.before_begin(), ++++testlist1.before_begin());
{ int init_values [] = { 2, 4, 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
}
{ //Now test swap when testlist2 is empty
list_type testlist1 (values.begin(), values.begin() + 2);
list_type testlist2;
testlist1.swap(testlist2);
BOOST_TEST (testlist1.empty());
{ int init_values [] = { 1, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
}
{ //Now test swap when testlist1 is empty
list_type testlist2 (values.begin(), values.begin() + 2);
list_type testlist1;
testlist1.swap(testlist2);
BOOST_TEST (testlist2.empty());
{ int init_values [] = { 1, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
}
{ //Now test when both are empty
list_type testlist1, testlist2;
testlist2.swap(testlist1);
BOOST_TEST (testlist1.empty() && testlist2.empty());
}
if(!list_type::linear)
{
list_type testlist1 (values.begin(), values.begin() + 2);
list_type testlist2 (values.begin() + 3, values.begin() + 5);
swap_nodes< node_algorithms >(values[0], values[2]);
{ int init_values [] = { 3, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
swap_nodes< node_algorithms >(values[2], values[4]);
{ int init_values [] = { 5, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
{ int init_values [] = { 4, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
}
if(!list_type::linear)
{
list_type testlist1 (values.begin(), values.begin()+1);
if(testlist1.size() != 1){
abort();
}
{ int init_values [] = { 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
swap_nodes< node_algorithms >(values[1], values[2]);
BOOST_TEST(testlist1.size() == 1);
BOOST_TEST(!(&values[1])->is_linked());
BOOST_TEST(!(&values[2])->is_linked());
{ int init_values [] = { 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
swap_nodes< node_algorithms >(values[0], values[2]);
BOOST_TEST(testlist1.size() == 1);
BOOST_TEST((&values[2])->is_linked());
BOOST_TEST(!(&values[0])->is_linked());
{ int init_values [] = { 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
swap_nodes< node_algorithms >(values[0], values[2]);
BOOST_TEST(testlist1.size() == 1);
BOOST_TEST(!(&values[2])->is_linked());
BOOST_TEST((&values[0])->is_linked());
{ int init_values [] = { 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
}
}
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_clone(ValueContainer& values)
{
list_type testlist1 (values.begin(), values.begin() + std::ptrdiff_t(values.size()));
list_type testlist2;
testlist2.clone_from(testlist1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
BOOST_TEST (testlist2 == testlist1);
testlist2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testlist2.empty());
}
template < typename ListType, typename ValueContainer >
void test_slist< ListType, ValueContainer >
::test_container_from_end(ValueContainer& values, detail::true_type)
{
list_type testlist1 (values.begin(), values.begin() + std::ptrdiff_t(values.size()));
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.end()));
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.cend()));
}
template < typename ValueTraits, bool ConstantTimeSize, bool Linear, bool CacheLast, bool Default_Holder, typename ValueContainer >
struct make_and_test_slist
: test_slist< slist< typename ValueTraits::value_type,
value_traits< ValueTraits >,
size_type< std::size_t >,
constant_time_size< ConstantTimeSize >,
linear<Linear>,
cache_last<CacheLast>
>,
ValueContainer
>
{};
template < typename ValueTraits, bool ConstantTimeSize, bool Linear, bool CacheLast, typename ValueContainer >
struct make_and_test_slist< ValueTraits, ConstantTimeSize, Linear, CacheLast, false, ValueContainer >
: test_slist< slist< typename ValueTraits::value_type,
value_traits< ValueTraits >,
size_type< std::size_t >,
constant_time_size< ConstantTimeSize >,
linear<Linear>,
cache_last<CacheLast>,
header_holder_type< heap_node_holder< typename ValueTraits::pointer > >
>,
ValueContainer
>
{};
template<class VoidPointer, bool constant_time_size, bool Default_Holder>
class test_main_template
{
public:
int operator()()
{
typedef testvalue< hooks<VoidPointer> > value_type;
std::vector< value_type > data (5);
for (std::size_t i = 0; i < 5u; ++i)
data[i].value_ = (int)i + 1;
make_and_test_slist < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, constant_time_size
, false
, false
, Default_Holder
, std::vector< value_type >
>::test_all(data);
make_and_test_slist < nonhook_node_member_value_traits< value_type,
typename hooks<VoidPointer>::nonhook_node_member_type,
&value_type::nhn_member_,
safe_link
>
, constant_time_size
, false
, false
, Default_Holder
, std::vector< value_type >
>::test_all(data);
//Now linear slists
make_and_test_slist < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, constant_time_size
, true
, false
, Default_Holder
, std::vector< value_type >
>::test_all(data);
//Now the same but caching the last node
make_and_test_slist < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, constant_time_size
, false
, true
, Default_Holder
, std::vector< value_type >
>::test_all(data);
//Now linear slists
make_and_test_slist < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, constant_time_size
, true
, true
, Default_Holder
, std::vector< value_type >
>::test_all(data);
return 0;
}
};
template<class VoidPointer, bool Default_Holder>
class test_main_template<VoidPointer, false, Default_Holder>
{
public:
int operator()()
{
typedef testvalue< hooks<VoidPointer> > value_type;
std::vector< value_type > data (5);
for (std::size_t i = 0; i < 5u; ++i)
data[i].value_ = (int)i + 1;
make_and_test_slist < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::auto_base_hook_type
>::type
, false
, false
, false
, Default_Holder
, std::vector< value_type >
>::test_all(data);
make_and_test_slist < nonhook_node_member_value_traits< value_type,
typename hooks<VoidPointer>::nonhook_node_member_type,
&value_type::nhn_member_,
safe_link
>
, false
, false
, true
, Default_Holder
, std::vector< value_type >
>::test_all(data);
make_and_test_slist < typename detail::get_member_value_traits
< member_hook< value_type
, typename hooks<VoidPointer>::member_hook_type
, &value_type::node_
>
>::type
, false
, true
, false
, Default_Holder
, std::vector< value_type >
>::test_all(data);
make_and_test_slist < typename detail::get_base_value_traits
< value_type
, typename hooks<VoidPointer>::base_hook_type
>::type
, false
, true
, true
, Default_Holder
, std::vector< value_type >
>::test_all(data);
return 0;
}
};
template < bool ConstantTimeSize >
struct test_main_template_bptr
{
int operator()()
{
typedef BPtr_Value value_type;
typedef BPtr_Value_Traits< List_BPtr_Node_Traits > list_value_traits;
typedef typename list_value_traits::node_ptr node_ptr;
typedef bounded_allocator< value_type > allocator_type;
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
allocator_type allocator;
{
bounded_reference_cont< value_type > ref_cont;
for (std::size_t i = 0; i < 5u; ++i)
{
node_ptr tmp = allocator.allocate(1);
new (tmp.raw()) value_type((int)i + 1);
ref_cont.push_back(*tmp);
}
test_slist < slist < value_type,
value_traits< list_value_traits >,
size_type< std::size_t >,
constant_time_size< ConstantTimeSize >,
header_holder_type< bounded_pointer_holder< value_type > >
>,
bounded_reference_cont< value_type >
>::test_all(ref_cont);
}
return 0;
}
};
int main(int, char* [])
{
// test (plain/smart pointers) x (nonconst/const size) x (void node allocator)
test_main_template<void*, false, true>()();
test_main_template<boost::intrusive::smart_ptr<void>, false, true>()();
test_main_template<void*, true, true>()();
test_main_template<boost::intrusive::smart_ptr<void>, true, true>()();
// test (bounded pointers) x ((nonconst/const size) x (special node allocator)
test_main_template_bptr< true >()();
test_main_template_bptr< false >()();
return boost::report_errors();
}

View File

@@ -0,0 +1,311 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_SMART_PTR_HPP
#define BOOST_INTRUSIVE_SMART_PTR_HPP
#include <boost/intrusive/pointer_plus_bits.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/iterator.hpp>
#include <boost/move/adl_move_swap.hpp>
#if (defined _MSC_VER)
# pragma once
#endif
namespace boost{
namespace intrusive{
namespace detail {
struct static_cast_tag {};
struct const_cast_tag {};
struct dynamic_cast_tag {};
struct reinterpret_cast_tag {};
} //namespace detail {
//Empty class
struct empty_type{};
template<class T>
struct random_it
: public iterator<std::random_access_iterator_tag, T, std::ptrdiff_t, T*, T&>
{
typedef const T* const_pointer;
typedef const T& const_reference;
};
template<> struct random_it<void>
{
typedef const void * const_pointer;
typedef empty_type& reference;
typedef const empty_type& const_reference;
typedef empty_type difference_type;
typedef empty_type iterator_category;
};
template<> struct random_it<const void>
{
typedef const void * const_pointer;
typedef const empty_type & reference;
typedef const empty_type & const_reference;
typedef empty_type difference_type;
typedef empty_type iterator_category;
};
template<> struct random_it<volatile void>
{
typedef const volatile void * const_pointer;
typedef empty_type& reference;
typedef const empty_type& const_reference;
typedef empty_type difference_type;
typedef empty_type iterator_category;
};
template<> struct random_it<const volatile void>
{
typedef const volatile void * const_pointer;
typedef const empty_type & reference;
typedef const empty_type & const_reference;
typedef empty_type difference_type;
typedef empty_type iterator_category;
};
} //namespace intrusive {
} //namespace boost {
namespace boost {
namespace intrusive {
template <class PointedType>
class smart_ptr
{
typedef random_it<PointedType> random_it_t;
typedef smart_ptr<PointedType> self_t;
typedef typename random_it_t::const_pointer const_pointer_t;
typedef typename random_it_t::const_reference const_reference_t;
void unspecified_bool_type_func() const {}
typedef void (self_t::*unspecified_bool_type)() const;
public:
typedef PointedType * pointer;
typedef typename random_it_t::reference reference;
typedef PointedType value_type;
typedef typename random_it_t::difference_type difference_type;
typedef typename random_it_t::iterator_category iterator_category;
PointedType *m_ptr;
public: //Public Functions
smart_ptr()
: m_ptr(0)
{}
//!Constructor from other smart_ptr
smart_ptr(const smart_ptr& ptr)
: m_ptr(ptr.m_ptr)
{}
static smart_ptr pointer_to(reference r)
{ smart_ptr p; p.m_ptr = &r; return p; }
//!Constructor from other smart_ptr. If pointers of pointee types are
//!convertible, offset_ptrs will be convertibles. Never throws.
template<class T2>
smart_ptr(const smart_ptr<T2> &ptr)
: m_ptr(ptr.m_ptr)
{}
pointer get() const
{ return m_ptr; }
void set(pointer p)
{ m_ptr = p; }
//!Pointer-like -> operator. It can return 0 pointer. Never throws.
pointer operator->() const
{ return m_ptr; }
//!Dereferencing operator, if it is a null smart_ptr behavior
//! is undefined. Never throws.
reference operator* () const
{ return *m_ptr; }
//!Indexing operator. Never throws.
reference operator[](std::ptrdiff_t idx) const
{ return m_ptr[idx]; }
//!Assignment from other smart_ptr. Never throws.
smart_ptr& operator= (const smart_ptr & pt)
{ m_ptr = pt.m_ptr; return *this; }
//!Assignment from related smart_ptr. If pointers of pointee types
//! are assignable, offset_ptrs will be assignable. Never throws.
template <class T2>
smart_ptr& operator= (const smart_ptr<T2> & pt)
{ m_ptr = pt.m_ptr; return *this; }
//!smart_ptr + std::ptrdiff_t. Never throws.
smart_ptr operator+ (std::ptrdiff_t offset) const
{ smart_ptr s; s.m_ptr = m_ptr + offset; return s; }
//!smart_ptr - std::ptrdiff_t. Never throws.
smart_ptr operator- (std::ptrdiff_t offset) const
{ smart_ptr s; s.m_ptr = m_ptr - offset; return s; }
//!smart_ptr += std::ptrdiff_t. Never throws.
smart_ptr &operator+= (std::ptrdiff_t offset)
{ m_ptr += offset; return *this; }
//!smart_ptr -= std::ptrdiff_t. Never throws.
smart_ptr &operator-= (std::ptrdiff_t offset)
{ m_ptr -= offset; return *this; }
//!++smart_ptr. Never throws.
smart_ptr& operator++ (void)
{ ++m_ptr; return *this; }
//!smart_ptr++. Never throws.
smart_ptr operator++ (int)
{ smart_ptr temp(*this); ++*this; return temp; }
//!--smart_ptr. Never throws.
smart_ptr& operator-- (void)
{ --m_ptr; return *this; }
//!smart_ptr--. Never throws.
smart_ptr operator-- (int)
{ smart_ptr temp(*this); --*this; return temp; }
//!safe bool conversion operator. Never throws.
operator unspecified_bool_type() const
{ return m_ptr? &self_t::unspecified_bool_type_func : 0; }
//!Not operator. Not needed in theory, but improves portability.
//!Never throws.
bool operator! () const
{ return m_ptr == 0; }
//!swap
friend void swap(smart_ptr& x, smart_ptr& y)
{ boost::adl_move_swap(x.m_ptr, y.m_ptr); }
};
//!smart_ptr<T1> == smart_ptr<T2>. Never throws.
template<class T1, class T2>
inline bool operator== (const smart_ptr<T1> &pt1,
const smart_ptr<T2> &pt2)
{ return pt1.operator->() == pt2.operator->(); }
//!smart_ptr<T1> != smart_ptr<T2>. Never throws.
template<class T1, class T2>
inline bool operator!= (const smart_ptr<T1> &pt1,
const smart_ptr<T2> &pt2)
{ return pt1.operator->() != pt2.operator->(); }
//!smart_ptr<T1> < smart_ptr<T2>. Never throws.
template<class T1, class T2>
inline bool operator< (const smart_ptr<T1> &pt1,
const smart_ptr<T2> &pt2)
{ return pt1.operator->() < pt2.operator->(); }
//!smart_ptr<T1> <= smart_ptr<T2>. Never throws.
template<class T1, class T2>
inline bool operator<= (const smart_ptr<T1> &pt1,
const smart_ptr<T2> &pt2)
{ return pt1.operator->() <= pt2.operator->(); }
//!smart_ptr<T1> > smart_ptr<T2>. Never throws.
template<class T1, class T2>
inline bool operator> (const smart_ptr<T1> &pt1,
const smart_ptr<T2> &pt2)
{ return pt1.operator->() > pt2.operator->(); }
//!smart_ptr<T1> >= smart_ptr<T2>. Never throws.
template<class T1, class T2>
inline bool operator>= (const smart_ptr<T1> &pt1,
const smart_ptr<T2> &pt2)
{ return pt1.operator->() >= pt2.operator->(); }
//!operator<<
template<class E, class T, class Y>
inline std::basic_ostream<E, T> & operator<<
(std::basic_ostream<E, T> & os, smart_ptr<Y> const & p)
{ return os << p.operator->(); }
//!operator>>
template<class E, class T, class Y>
inline std::basic_istream<E, T> & operator>>
(std::basic_istream<E, T> & os, smart_ptr<Y> & p)
{ Y * tmp; return os >> tmp; p = tmp; }
//!std::ptrdiff_t + smart_ptr
template<class T>
inline smart_ptr<T> operator+(std::ptrdiff_t diff, const smart_ptr<T>& right)
{ return right + diff; }
//!smart_ptr - smart_ptr
template<class T, class T2>
inline std::ptrdiff_t operator- (const smart_ptr<T> &pt, const smart_ptr<T2> &pt2)
{ return pt.operator->()- pt2.operator->(); }
} //namespace intrusive {
} //namespace boost {
namespace boost{
//This is to support embedding a bit in the pointer
//for intrusive containers, saving space
namespace intrusive {
template<std::size_t Alignment>
struct max_pointer_plus_bits<smart_ptr<void>, Alignment>
{
static const std::size_t value = max_pointer_plus_bits<void*, Alignment>::value;
};
template<class T, std::size_t NumBits>
struct pointer_plus_bits<smart_ptr<T>, NumBits>
{
typedef smart_ptr<T> pointer;
static pointer get_pointer(const pointer &n)
{
pointer p;
p.set(pointer_plus_bits<T*, NumBits>::get_pointer(n.get()));
return p;
}
static void set_pointer(pointer &n, pointer p)
{
T *raw_n = n.get();
pointer_plus_bits<T*, NumBits>::set_pointer(raw_n, p.operator->());
n.set(raw_n);
}
static std::size_t get_bits(const pointer &n)
{ return pointer_plus_bits<T*, NumBits>::get_bits(n.get()); }
static void set_bits(pointer &n, std::size_t c)
{
T *raw_n = n.operator->();
pointer_plus_bits<T*, NumBits>::set_bits(raw_n, c);
n.set(raw_n);
}
};
} //namespace intrusive
} //namespace boost{
#endif //#ifndef BOOST_INTRUSIVE_SMART_PTR_HPP

View File

@@ -0,0 +1,155 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/splay_set.hpp>
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "bs_test_common.hpp"
#include "generic_multiset_test.hpp"
using namespace boost::intrusive;
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type;
template < class Option1 =void
, class Option2 =void
>
struct container
{
typedef splay_multiset
< typename common_t::value_type
, value_traits<ValueTraits>
, constant_time_size<ConstantTimeSize>
, typename common_t::holder_opt
, typename common_t::key_of_value_opt
, Option1
, Option2
> type;
BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value));
};
};
enum HookType
{
Base,
Member,
NonMember
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type>
class test_main_template;
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//base
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::base_value_traits
, typename testval_traits_t::auto_base_value_traits
>::type base_hook_t;
test::test_generic_multiset
< rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//member
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::member_value_traits
, typename testval_traits_t::auto_member_value_traits
>::type member_hook_t;
test::test_generic_multiset
< rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//nonmember
test::test_generic_multiset
< rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template < bool ConstantTimeSize, bool Map >
struct test_main_template_bptr
{
static void execute()
{
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_multiset
< rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
int main()
{
//Combinations: VoidPointer x ConstantTimeSize x DefaultHolder x Map
//Minimize them selecting different combinations for raw and smart pointers
//Start with ('false', 'false', 'false') in sets and 'false', 'false', 'true' in multisets
//void pointer
test_main_template<void*, false, false, false, Base>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false, Member>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false, Base>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false, Member>::execute();
test_main_template<void*, true, true, true, NonMember>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true, Base>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true, Member>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute();
//test_main_template<smart_ptr<void>, true, true, false>::execute();
//test_main_template<smart_ptr<void>, true, true, true>::execute();
//bounded_ptr (bool ConstantTimeSize, bool Map)
test_main_template_bptr< false, false >::execute();
//test_main_template_bptr< false, true >::execute();
//test_main_template_bptr< true, false >::execute();
test_main_template_bptr< true, true >::execute();
return boost::report_errors();
}

View File

@@ -0,0 +1,155 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2015
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/splay_set.hpp>
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "bs_test_common.hpp"
#include "generic_set_test.hpp"
using namespace boost::intrusive;
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type;
template < class Option1 =void
, class Option2 =void
>
struct container
{
typedef splay_set
< typename common_t::value_type
, value_traits<ValueTraits>
, constant_time_size<ConstantTimeSize>
, typename common_t::holder_opt
, typename common_t::key_of_value_opt
, Option1
, Option2
> type;
BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value));
};
};
enum HookType
{
Base,
Member,
NonMember
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type>
class test_main_template;
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//base
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::base_value_traits
, typename testval_traits_t::auto_base_value_traits
>::type base_hook_t;
test::test_generic_set
< rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//member
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::member_value_traits
, typename testval_traits_t::auto_member_value_traits
>::type member_hook_t;
test::test_generic_set
< rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//nonmember
test::test_generic_set
< rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template < bool ConstantTimeSize, bool Map >
struct test_main_template_bptr
{
static void execute()
{
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_set
< rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
int main()
{
//Combinations: VoidPointer x ConstantTimeSize x DefaultHolder x Map
//Minimize them selecting different combinations for raw and smart pointers
//Start with ('false', 'false', 'false') in sets and 'false', 'false', 'true' in multisets
//void pointer
test_main_template<void*, false, false, false, Base>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false, Member>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false, Base>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false, Member>::execute();
test_main_template<void*, true, true, true, NonMember>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true, Base>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true, Member>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute();
//test_main_template<smart_ptr<void>, true, true, false>::execute();
//test_main_template<smart_ptr<void>, true, true, true>::execute();
//bounded_ptr (bool ConstantTimeSize, bool Map)
test_main_template_bptr< false, false >::execute();
//test_main_template_bptr< false, true >::execute();
//test_main_template_bptr< true, false >::execute();
test_main_template_bptr< true, true >::execute();
return boost::report_errors();
}

View File

@@ -0,0 +1,157 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <vector>
using namespace boost::intrusive;
class MyClass
{
public:
int int_;
MyClass(int i = 0)
: int_(i)
{}
friend bool operator<(const MyClass &l, const MyClass &r)
{ return l.int_ < r.int_; }
friend bool operator==(const MyClass &l, const MyClass &r)
{ return l.int_ == r.int_; }
friend std::size_t hash_value(const MyClass &v)
{ return boost::hash_value(v.int_); }
};
template<class T, class NodeTraits>
struct stateful_value_traits
{
typedef NodeTraits node_traits;
typedef typename node_traits::node node;
typedef typename node_traits::node_ptr node_ptr;
typedef typename node_traits::const_node_ptr const_node_ptr;
typedef T value_type;
typedef typename pointer_traits<node_ptr>::
template rebind_pointer<T>::type pointer;
typedef typename pointer_traits<node_ptr>::
template rebind_pointer<const T>::type const_pointer;
static const link_mode_type link_mode = normal_link;
stateful_value_traits(pointer vals, node_ptr node_array)
: values_(vals), node_array_(node_array)
{}
node_ptr to_node_ptr (value_type &value) const
{ return node_array_ + (&value - values_); }
const_node_ptr to_node_ptr (const value_type &value) const
{ return node_array_ + (&value - values_); }
pointer to_value_ptr(node_ptr n) const
{ return values_ + (n - node_array_); }
const_pointer to_value_ptr(const_node_ptr n) const
{ return values_ + (n - node_array_); }
pointer values_;
node_ptr node_array_;
};
//Define a list that will store MyClass using the external hook
typedef stateful_value_traits< MyClass, list_node_traits<void*> > list_traits;
typedef list<MyClass, value_traits<list_traits> > List;
//Define a slist that will store MyClass using the external hook
typedef stateful_value_traits< MyClass, slist_node_traits<void*> > slist_traits;
typedef slist<MyClass, value_traits<slist_traits> > Slist;
//Define a set that will store MyClass using the external hook
typedef stateful_value_traits< MyClass, rbtree_node_traits<void*> > rbtree_traits;
typedef set<MyClass, value_traits<rbtree_traits> > Set;
//uset uses the same traits as slist
typedef unordered_set<MyClass, value_traits<slist_traits> > Uset;
typedef list_traits::node list_node_t;
typedef slist_traits::node slist_node_t;
typedef rbtree_traits::node rbtree_node_t;
const int NumElements = 100;
MyClass values [NumElements];
list_node_t list_hook_array [NumElements];
slist_node_t slist_hook_array [NumElements];
rbtree_node_t rbtree_hook_array [NumElements];
slist_node_t uset_hook_array [NumElements];
int main()
{
//Create several MyClass objects, each one with a different value
for(int i = 0; i < NumElements; ++i)
values[i].int_ = i;
Uset::bucket_type buckets[NumElements];
List my_list (list_traits (values, list_hook_array));
Slist my_slist(slist_traits(values, slist_hook_array));
Set my_set (std::less<MyClass>(), rbtree_traits(values, rbtree_hook_array));
Uset my_uset ( Uset::bucket_traits(buckets, NumElements)
, boost::hash<MyClass>()
, std::equal_to<MyClass>()
, slist_traits(values, uset_hook_array)
);
//Now insert them in containers
for(MyClass * it(&values[0]), *itend(&values[NumElements])
; it != itend
; ++it){
my_list.push_front(*it);
if(&*my_list.iterator_to(*it) != &my_list.front())
return 1;
my_slist.push_front(*it);
if(&*my_slist.iterator_to(*it) != &my_slist.front())
return 1;
Set::iterator sit = my_set.insert(*it).first;
if(&*my_set.iterator_to(*it) != &*sit)
return 1;
Uset::iterator uit = my_uset.insert(*it).first;
my_uset.insert(*it);
if(&*my_uset.iterator_to(*it) != &*uit)
return 1;
}
//Now test lists
{
List::const_iterator list_it (my_list.cbegin());
Slist::const_iterator slist_it(my_slist.cbegin());
Set::const_reverse_iterator set_rit(my_set.crbegin());
MyClass *it_val(&values[NumElements]), *it_rbeg_val(&values[0]);
//Test the objects inserted in the base hook list
for(; it_val != it_rbeg_val; --it_val, ++list_it, ++slist_it, ++set_rit){
if(&*list_it != &it_val[-1]) return 1;
if(&*slist_it != &it_val[-1]) return 1;
if(&*set_rit != &it_val[-1]) return 1;
if(my_uset.find(it_val[-1]) == my_uset.cend()) return 1;
}
}
return 0;
}

View File

@@ -0,0 +1,57 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_TEST_TEST_COMMON_HPP
#define BOOST_INTRUSIVE_TEST_TEST_COMMON_HPP
#include <boost/intrusive/bs_set_hook.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include "bptr_value.hpp"
namespace boost {
namespace intrusive {
template <class KeyOfValueOption, class Map>
struct key_type_tester
{
struct empty_default{};
typedef typename pack_options< empty_default, KeyOfValueOption >::type::key_of_value key_of_value_t;
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same< KeyOfValueOption
, key_of_value<int_holder_key_of_value<typename Map::value_type> >
>::value ));
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same< key_of_value_t
, int_holder_key_of_value<typename Map::value_type>
>::value ));
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same< typename Map::key_type
, typename key_of_value_t::type >::value ));
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same< typename Map::key_of_value
, key_of_value_t >::value ));
static const bool value = true;
};
template <class Map>
struct key_type_tester<void, Map>
{
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same< typename Map::key_type
, typename Map::value_type
>::value ));
BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same< typename Map::key_of_value
, boost::intrusive::detail::identity< typename Map::value_type>
>::value ));
static const bool value = true;
};
} //namespace intrusive {
} //namespace boost {
#endif //BOOST_INTRUSIVE_TEST_TEST_COMMON_HPP

View File

@@ -0,0 +1,572 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_TEST_CONTAINER_HPP
#define BOOST_INTRUSIVE_TEST_CONTAINER_HPP
#include <boost/core/lightweight_test.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/simple_disposers.hpp>
#include <boost/intrusive/detail/iterator.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/move/adl_move_swap.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/static_assert.hpp>
#include "iterator_test.hpp"
#include <cstdlib>
namespace boost {
namespace intrusive {
namespace test {
BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(is_unordered, hasher)
template<class Container>
struct test_container_typedefs
{
typedef typename Container::value_type value_type;
typedef typename Container::iterator iterator;
typedef typename Container::const_iterator const_iterator;
typedef typename Container::reference reference;
typedef typename Container::const_reference const_reference;
typedef typename Container::pointer pointer;
typedef typename Container::const_pointer const_pointer;
typedef typename Container::difference_type difference_type;
typedef typename Container::size_type size_type;
typedef typename Container::value_traits value_traits;
};
template< class Container >
void test_container( Container & c )
{
typedef typename Container::const_iterator const_iterator;
typedef typename Container::iterator iterator;
typedef typename Container::size_type size_type;
{test_container_typedefs<Container> dummy; (void)dummy;}
const size_type num_elem = c.size();
BOOST_TEST( c.empty() == (num_elem == 0) );
{
iterator it(c.begin()), itend(c.end());
size_type i;
for(i = 0; i < num_elem; ++i){
++it;
}
BOOST_TEST( it == itend );
BOOST_TEST( c.size() == i );
}
//Check iterator conversion
BOOST_TEST(const_iterator(c.begin()) == c.cbegin() );
{
const_iterator it(c.cbegin()), itend(c.cend());
size_type i;
for(i = 0; i < num_elem; ++i){
++it;
}
BOOST_TEST( it == itend );
BOOST_TEST( c.size() == i );
}
static_cast<const Container&>(c).check();
//Very basic test for comparisons
{
BOOST_TEST(c == c);
BOOST_TEST(!(c != c));
BOOST_TEST(!(c < c));
BOOST_TEST(c <= c);
BOOST_TEST(!(c > c));
BOOST_TEST(c >= c);
}
}
template< class Container, class Data >
void test_sequence_container(Container & c, Data & d)
{
assert( d.size() > 2 );
{
c.clear();
BOOST_TEST( c.size() == 0 );
BOOST_TEST( c.empty() );
{
typename Data::iterator i = d.begin();
c.insert( c.begin(), *i );
BOOST_TEST( &*c.iterator_to(*c.begin()) == &*i );
BOOST_TEST( &*c.iterator_to(*c.cbegin()) == &*i );
BOOST_TEST( &*Container::s_iterator_to(*c.begin()) == &*i );
BOOST_TEST( &*Container::s_iterator_to(*c.cbegin()) == &*i );
c.insert( c.end(), *(++i) );
}
BOOST_TEST( c.size() == 2 );
BOOST_TEST( !c.empty() );
typename Container::iterator i;
i = c.erase( c.begin() );
BOOST_TEST( c.size() == 1 );
BOOST_TEST( !c.empty() );
i = c.erase( c.begin() );
BOOST_TEST( c.size() == 0 );
BOOST_TEST( c.empty() );
c.insert( c.begin(), *d.begin() );
BOOST_TEST( c.size() == 1 );
BOOST_TEST( !c.empty() );
{
typename Data::iterator di = d.begin();
++++di;
c.insert( c.begin(), *(di) );
}
i = c.erase( c.begin(), c.end() );
BOOST_TEST( i == c.end() );
BOOST_TEST( c.empty() );
c.insert( c.begin(), *d.begin() );
BOOST_TEST( c.size() == 1 );
BOOST_TEST( c.begin() != c.end() );
i = c.erase_and_dispose( c.begin(), detail::null_disposer() );
BOOST_TEST( i == c.begin() );
c.assign(d.begin(), d.end());
BOOST_TEST( c.size() == d.size() );
c.clear();
BOOST_TEST( c.size() == 0 );
BOOST_TEST( c.empty() );
}
{
c.clear();
c.insert( c.begin(), d.begin(), d.end() );
Container move_c(::boost::move(c));
BOOST_TEST( move_c.size() == d.size() );
BOOST_TEST( c.empty());
c = ::boost::move(move_c);
BOOST_TEST( c.size() == d.size() );
BOOST_TEST( move_c.empty());
}
}
template< class Container, class Data >
void test_common_unordered_and_associative_container(Container & c, Data & d, boost::intrusive::detail::true_ unordered)
{
(void)unordered;
typedef typename Container::size_type size_type;
typedef typename Container::key_of_value key_of_value;
typedef typename Container::iterator iterator;
typedef typename Container::const_iterator const_iterator;
assert( d.size() > 2 );
c.clear();
c.insert(d.begin(), d.end());
{
Container const &cc = c;
for( typename Data::const_iterator di = d.begin(), de = d.end();
di != de; ++di )
{
BOOST_TEST( cc.find(key_of_value()(*di), c.hash_function(), c.key_eq()) != cc.end() );
std::pair<const_iterator, const_iterator> rdi = cc.equal_range(key_of_value()(*di), c.hash_function(), c.key_eq());
BOOST_TEST(rdi.first != rdi.second);
BOOST_TEST(size_type(boost::intrusive::iterator_distance(rdi.first, rdi.second)) == cc.count(key_of_value()(*di), c.hash_function(), c.key_eq()));
}
for( iterator ci = c.begin(), ce = c.end(); ci != ce; )
{
BOOST_TEST( c.find(key_of_value()(*ci)) != c.end() );
std::pair<iterator, iterator> rci = c.equal_range(key_of_value()(*ci), c.hash_function(), c.key_eq());
BOOST_TEST(rci.first != rci.second);
size_type const sc = c.count(key_of_value()(*ci), c.hash_function(), c.key_eq());
BOOST_TEST(size_type(boost::intrusive::iterator_distance(rci.first, rci.second)) == sc);
BOOST_TEST(sc == c.erase(key_of_value()(*ci), c.hash_function(), c.key_eq()));
ci = rci.second;
}
BOOST_TEST(c.empty());
}
c.clear();
c.insert(d.begin(), d.end());
typename Data::const_iterator db = d.begin();
typename Data::const_iterator da = db++;
size_type old_size = c.size();
c.erase(key_of_value()(*da), c.hash_function(), c.key_eq());
BOOST_TEST( c.size() == old_size-1 );
//This should not eras anyone
size_type second_erase = c.erase_and_dispose
( key_of_value()(*da), c.hash_function(), c.key_eq(), detail::null_disposer() );
BOOST_TEST( second_erase == 0 );
BOOST_TEST( c.count(key_of_value()(*da), c.hash_function(), c.key_eq()) == 0 );
BOOST_TEST( c.count(key_of_value()(*db), c.hash_function(), c.key_eq()) != 0 );
BOOST_TEST( c.find(key_of_value()(*da), c.hash_function(), c.key_eq()) == c.end() );
BOOST_TEST( c.find(key_of_value()(*db), c.hash_function(), c.key_eq()) != c.end() );
BOOST_TEST( c.equal_range(key_of_value()(*db), c.hash_function(), c.key_eq()).first != c.end() );
c.clear();
BOOST_TEST( c.equal_range(key_of_value()(*da), c.hash_function(), c.key_eq()).first == c.end() );
//
//suggested_upper_bucket_count
//
//Maximum fallbacks to the highest possible value
typename Container::size_type sz = Container::suggested_upper_bucket_count(size_type(-1));
BOOST_TEST( sz > size_type(-1)/2 );
//In the rest of cases the upper bound is returned
sz = Container::suggested_upper_bucket_count(size_type(-1)/2);
BOOST_TEST( sz >= size_type(-1)/2 );
sz = Container::suggested_upper_bucket_count(size_type(-1)/4);
BOOST_TEST( sz >= size_type(-1)/4 );
sz = Container::suggested_upper_bucket_count(0);
BOOST_TEST( sz > 0 );
//
//suggested_lower_bucket_count
//
sz = Container::suggested_lower_bucket_count(size_type(-1));
BOOST_TEST( sz <= size_type(-1) );
//In the rest of cases the lower bound is returned
sz = Container::suggested_lower_bucket_count(size_type(-1)/2);
BOOST_TEST( sz <= size_type(-1)/2 );
sz = Container::suggested_lower_bucket_count(size_type(-1)/4);
BOOST_TEST( sz <= size_type(-1)/4 );
//Minimum fallbacks to the lowest possible value
sz = Container::suggested_upper_bucket_count(0);
BOOST_TEST( sz > 0 );
}
template< class Container, class Data >
void test_common_unordered_and_associative_container(Container & c, Data & d, boost::intrusive::detail::false_ unordered)
{
(void)unordered;
typedef typename Container::size_type size_type;
typedef typename Container::key_of_value key_of_value;
typedef typename Container::iterator iterator;
typedef typename Container::const_iterator const_iterator;
assert( d.size() > 2 );
c.clear();
typename Container::reference r = *d.begin();
c.insert(d.begin(), ++d.begin());
BOOST_TEST( &*Container::s_iterator_to(*c.begin()) == &r );
BOOST_TEST( &*Container::s_iterator_to(*c.cbegin()) == &r );
c.clear();
c.insert(d.begin(), d.end());
{
Container const &cc = c;
for( typename Data::const_iterator di = d.begin(), de = d.end();
di != de; ++di )
{
BOOST_TEST( cc.find(key_of_value()(*di), c.key_comp()) != cc.end() );
std::pair<const_iterator, const_iterator> rdi = cc.equal_range(key_of_value()(*di), c.key_comp());
BOOST_TEST(rdi.first != rdi.second);
BOOST_TEST(size_type(boost::intrusive::iterator_distance(rdi.first, rdi.second)) == cc.count(key_of_value()(*di), c.key_comp()));
}
for( iterator ci = c.begin(), ce = c.end(); ci != ce; )
{
BOOST_TEST( c.find(key_of_value()(*ci)) != c.end() );
std::pair<iterator, iterator> rci = c.equal_range(key_of_value()(*ci), c.key_comp());
BOOST_TEST(rci.first != rci.second);
size_type const sc = c.count(key_of_value()(*ci), c.key_comp());
BOOST_TEST(size_type(boost::intrusive::iterator_distance(rci.first, rci.second)) == sc);
BOOST_TEST(sc == c.erase(key_of_value()(*ci), c.key_comp()));
ci = rci.second;
}
BOOST_TEST(c.empty());
}
c.clear();
c.insert(d.begin(), d.end());
typename Data::const_iterator db = d.begin();
typename Data::const_iterator da = db++;
size_type old_size = c.size();
c.erase(key_of_value()(*da), c.key_comp());
BOOST_TEST( c.size() == old_size-1 );
//This should not erase any
size_type second_erase = c.erase_and_dispose( key_of_value()(*da), c.key_comp(), detail::null_disposer() );
BOOST_TEST( second_erase == 0 );
BOOST_TEST( c.count(key_of_value()(*da), c.key_comp()) == 0 );
BOOST_TEST( c.count(key_of_value()(*db), c.key_comp()) != 0 );
BOOST_TEST( c.find(key_of_value()(*da), c.key_comp()) == c.end() );
BOOST_TEST( c.find(key_of_value()(*db), c.key_comp()) != c.end() );
BOOST_TEST( c.equal_range(key_of_value()(*db), c.key_comp()).first != c.end() );
c.clear();
BOOST_TEST( c.equal_range(key_of_value()(*da), c.key_comp()).first == c.end() );
}
template< class Container, class Data >
void test_common_unordered_and_associative_container(Container & c, Data & d)
{
typedef typename Container::size_type size_type;
typedef typename Container::key_of_value key_of_value;
typedef typename Container::iterator iterator;
typedef typename Container::const_iterator const_iterator;
{
assert( d.size() > 2 );
c.clear();
typename Container::reference r = *d.begin();
c.insert(d.begin(), ++d.begin());
BOOST_TEST( &*c.iterator_to(*c.begin()) == &r );
BOOST_TEST( &*c.iterator_to(*c.cbegin()) == &r );
c.clear();
c.insert(d.begin(), d.end());
Container const &cc = c;
for( typename Data::const_iterator di = d.begin(), de = d.end();
di != de; ++di )
{
BOOST_TEST( cc.find(key_of_value()(*di)) != cc.end() );
std::pair<const_iterator, const_iterator> rdi = cc.equal_range(key_of_value()(*di));
BOOST_TEST(rdi.first != rdi.second);
BOOST_TEST(size_type(boost::intrusive::iterator_distance(rdi.first, rdi.second)) == cc.count(key_of_value()(*di)));
}
for( iterator ci = c.begin(), ce = c.end(); ci != ce; )
{
BOOST_TEST( c.find(key_of_value()(*ci)) != c.end() );
std::pair<iterator, iterator> rci = c.equal_range(key_of_value()(*ci));
BOOST_TEST(rci.first != rci.second);
size_type const sc = c.count(key_of_value()(*ci));
BOOST_TEST(size_type(boost::intrusive::iterator_distance(rci.first, rci.second)) == sc);
BOOST_TEST(sc == c.erase(key_of_value()(*ci)));
ci = rci.second;
}
BOOST_TEST(c.empty());
}
{
c.clear();
c.insert(d.begin(), d.end());
typename Data::const_iterator db = d.begin();
typename Data::const_iterator da = db++;
size_type old_size = c.size();
c.erase(key_of_value()(*da));
BOOST_TEST( c.size() == old_size-1 );
//This should erase nothing
size_type second_erase = c.erase_and_dispose( key_of_value()(*da), detail::null_disposer() );
BOOST_TEST( second_erase == 0 );
BOOST_TEST( c.count(key_of_value()(*da)) == 0 );
BOOST_TEST( c.count(key_of_value()(*db)) != 0 );
BOOST_TEST( c.find(key_of_value()(*da)) == c.end() );
BOOST_TEST( c.find(key_of_value()(*db)) != c.end() );
BOOST_TEST( c.equal_range(key_of_value()(*db)).first != c.end() );
BOOST_TEST( c.equal_range(key_of_value()(*da)).first == c.equal_range(key_of_value()(*da)).second );
}
{
c.clear();
c.insert( d.begin(), d.end() );
size_type orig_size = c.size();
Container move_c(::boost::move(c));
BOOST_TEST(orig_size == move_c.size());
BOOST_TEST( c.empty());
for( typename Data::const_iterator di = d.begin(), de = d.end();
di != de; ++di )
{ BOOST_TEST( move_c.find(key_of_value()(*di)) != move_c.end() ); }
c = ::boost::move(move_c);
for( typename Data::const_iterator di = d.begin(), de = d.end();
di != de; ++di )
{ BOOST_TEST( c.find(key_of_value()(*di)) != c.end() ); }
BOOST_TEST( move_c.empty());
}
typedef detail::bool_<is_unordered<Container>::value> enabler;
test_common_unordered_and_associative_container(c, d, enabler());
}
template< class Container, class Data >
void test_associative_container_invariants(Container & c, Data & d)
{
typedef typename Container::const_iterator const_iterator;
typedef typename Container::key_of_value key_of_value;
for( typename Data::const_iterator di = d.begin(), de = d.end();
di != de; ++di)
{
const_iterator ci = c.find(key_of_value()(*di));
BOOST_TEST( ci != c.end() );
BOOST_TEST( ! c.value_comp()(*ci, *di) );
BOOST_TEST( ! c.key_comp()(key_of_value()(*ci), key_of_value()(*di)) );
const_iterator cil = c.lower_bound(key_of_value()(*di));
const_iterator ciu = c.upper_bound(key_of_value()(*di));
std::pair<const_iterator, const_iterator> er = c.equal_range(key_of_value()(*di));
BOOST_TEST( cil == er.first );
BOOST_TEST( ciu == er.second );
if(ciu != c.end()){
BOOST_TEST( c.value_comp()(*cil, *ciu) );
BOOST_TEST( c.key_comp()(key_of_value()(*cil), key_of_value()(*ciu)) );
}
if(c.count(key_of_value()(*di)) > 1){
const_iterator ci_next = cil; ++ci_next;
for( ; ci_next != ciu; ++cil, ++ci_next){
BOOST_TEST( !c.value_comp()(*ci_next, *cil) );
BOOST_TEST( !c.key_comp()(key_of_value()(*ci_next), key_of_value()(*cil)) );
}
}
}
}
template< class Container, class Data >
void test_associative_container(Container & c, Data & d)
{
assert( d.size() > 2 );
c.clear();
c.insert(d.begin(),d.end());
test_associative_container_invariants(c, d);
const Container & cr = c;
test_associative_container_invariants(cr, d);
}
template< class Container, class Data >
void test_unordered_associative_container_invariants(Container & c, Data & d)
{
typedef typename Container::size_type size_type;
typedef typename Container::const_iterator const_iterator;
typedef typename Container::key_of_value key_of_value;
for( typename Data::const_iterator di = d.begin(), de = d.end() ;
di != de ; ++di ){
const_iterator i = c.find(key_of_value()(*di));
size_type nb = c.bucket(key_of_value()(*i));
size_type bucket_elem = (size_type) boost::intrusive::iterator_distance(c.begin(nb), c.end(nb));
BOOST_TEST( bucket_elem == c.bucket_size(nb) );
BOOST_TEST( &*c.local_iterator_to(*c.find(key_of_value()(*di))) == &*i );
BOOST_TEST( &*c.local_iterator_to(*const_cast<const Container &>(c).find(key_of_value()(*di))) == &*i );
BOOST_TEST( &*Container::s_local_iterator_to(*c.find(key_of_value()(*di))) == &*i );
BOOST_TEST( &*Container::s_local_iterator_to(*const_cast<const Container &>(c).find(key_of_value()(*di))) == &*i );
std::pair<const_iterator, const_iterator> er = c.equal_range(key_of_value()(*di));
size_type cnt = (size_type) boost::intrusive::iterator_distance(er.first, er.second);
BOOST_TEST( cnt == c.count(key_of_value()(*di)));
if(cnt > 1){
const_iterator n = er.first;
i = n++;
const_iterator e = er.second;
for(; n != e; ++i, ++n){
BOOST_TEST( c.key_eq()(key_of_value()(*i), key_of_value()(*n)) );
BOOST_TEST( (c.hash_function()(key_of_value()(*i))) == (c.hash_function()(key_of_value()(*n))) );
}
}
}
std::size_t blen = c.bucket_count();
std::size_t total_objects = 0;
for(size_type i = 0; i < blen; ++i){
total_objects += std::size_t(c.bucket_size(i));
}
BOOST_TEST( total_objects == c.size() );
}
template< class Container, class Data >
void test_unordered_associative_container(Container & c, Data & d)
{
c.clear();
c.insert( d.begin(), d.end() );
test_unordered_associative_container_invariants(c, d);
const Container & cr = c;
test_unordered_associative_container_invariants(cr, d);
}
template< class Container, class Data >
void test_unique_container(Container & c, Data & d)
{
//typedef typename Container::value_type value_type;
c.clear();
c.insert(d.begin(),d.end());
typename Container::size_type old_size = c.size();
//value_type v(*d.begin());
//c.insert(v);
Data d2(1);
(&d2.front())->value_ = (&d.front())->value_;
c.insert(d2.front());
BOOST_TEST( c.size() == old_size );
c.clear();
}
template< class Container, class Data >
void test_non_unique_container(Container & c, Data & d)
{
//typedef typename Container::value_type value_type;
c.clear();
c.insert(d.begin(),d.end());
typename Container::size_type old_size = c.size();
//value_type v(*d.begin());
//c.insert(v);
Data d2(1);
(&d2.front())->value_ = (&d.front())->value_;
c.insert(d2.front());
BOOST_TEST( c.size() == (old_size+1) );
c.clear();
}
template< class Container, class Data >
void test_maybe_unique_container(Container & c, Data & d, detail::false_)//is_unique
{ test_unique_container(c, d); }
template< class Container, class Data >
void test_maybe_unique_container(Container & c, Data & d, detail::true_)//!is_unique
{ test_non_unique_container(c, d); }
template< class RandomIt >
void random_shuffle( RandomIt first, RandomIt last )
{
typedef typename boost::intrusive::iterator_traits<RandomIt>::difference_type difference_type;
difference_type n = last - first;
for (difference_type i = n-1; i > 0; --i) {
difference_type j = std::rand() % (i+1);
if(j != i) {
boost::adl_move_swap(first[i], first[j]);
}
}
}
}}}
#endif //#ifndef BOOST_INTRUSIVE_TEST_CONTAINER_HPP

View File

@@ -0,0 +1,81 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_TEST_TEST_MACROS_HPP
#define BOOST_INTRUSIVE_TEST_TEST_MACROS_HPP
#include <boost/intrusive/intrusive_fwd.hpp>
#include <algorithm> //std::unique
namespace boost{
namespace intrusive{
namespace test{
template <class T>
struct is_multikey_true
{
typedef char yes_type;
template<bool IsMultikey>
struct two { yes_type _[1u+unsigned(IsMultikey)]; };
template <class U> static yes_type test(...);
template <class U> static two<U::is_multikey>test(int);
static const bool value = sizeof(test<T>(0)) != sizeof(yes_type);
};
} //namespace test{
template<class It1, class It2>
bool test_equal(It1 f1, It1 l1, It2 f2)
{
while(f1 != l1){
if(*f1 != *f2){
return false;
}
++f1;
++f2;
}
return true;
}
#define TEST_INTRUSIVE_SEQUENCE( INTVALUES, ITERATOR )\
{ \
BOOST_TEST (boost::intrusive::test_equal(&INTVALUES[0], &INTVALUES[0] + sizeof(INTVALUES)/sizeof(INTVALUES[0]), ITERATOR) ); \
}
#define TEST_INTRUSIVE_SEQUENCE_EXPECTED( EXPECTEDVECTOR, ITERATOR )\
{ \
BOOST_TEST (boost::intrusive::test_equal(EXPECTEDVECTOR.begin(), EXPECTEDVECTOR.end(), ITERATOR) ); \
}
namespace test{
template<class Container, class Vector>
void test_intrusive_maybe_unique(const Container &c, Vector &v)
{
if(!is_multikey_true<Container>::value)
v.erase(std::unique(v.begin(), v.end()), v.end());
BOOST_TEST (boost::intrusive::test_equal(v.begin(), v.end(), c.begin()) );
}
} //namespace test{
#define TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE(INTVALUES, CONTAINER)\
{\
boost::container::vector<int>v(&INTVALUES[0], &INTVALUES[0] + sizeof(INTVALUES)/sizeof(INTVALUES[0]));\
boost::intrusive::test::test_intrusive_maybe_unique(CONTAINER, v);\
}\
//
} //namespace boost{
} //namespace intrusive{
#endif

View File

@@ -0,0 +1,157 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "bs_test_common.hpp"
#include "generic_multiset_test.hpp"
#include <boost/intrusive/treap_set.hpp>
using namespace boost::intrusive;
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type;
template < class Option1 =void
, class Option2 =void
>
struct container
{
typedef treap_multiset
< typename common_t::value_type
, value_traits<ValueTraits>
, constant_time_size<ConstantTimeSize>
, typename common_t::holder_opt
, typename common_t::key_of_value_opt
, typename common_t::prio_of_value_opt
, Option1
, Option2
> type;
BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value));
};
};
enum HookType
{
Base,
Member,
NonMember
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type>
class test_main_template;
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//base
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::base_value_traits
, typename testval_traits_t::auto_base_value_traits
>::type base_hook_t;
test::test_generic_multiset
< rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//member
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::member_value_traits
, typename testval_traits_t::auto_member_value_traits
>::type member_hook_t;
test::test_generic_multiset
< rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//nonmember
test::test_generic_multiset
< rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template < bool ConstantTimeSize, bool Map >
struct test_main_template_bptr
{
static void execute()
{
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_multiset
< rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
int main()
{
//Combinations: VoidPointer x ConstantTimeSize x DefaultHolder x Map
//Minimize them selecting different combinations for raw and smart pointers
//Start with ('false', 'false', 'false') in sets and 'false', 'false', 'true' in multisets
//void pointer
test_main_template<void*, false, false, false, Base>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false, Member>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false, Base>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false, Member>::execute();
test_main_template<void*, true, true, true, NonMember>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true, Base>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true, Member>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute();
//test_main_template<smart_ptr<void>, true, true, false>::execute();
//test_main_template<smart_ptr<void>, true, true, true>::execute();
//bounded_ptr (bool ConstantTimeSize, bool Map)
test_main_template_bptr< false, false >::execute();
//test_main_template_bptr< false, true >::execute();
//test_main_template_bptr< true, false >::execute();
test_main_template_bptr< true, true >::execute();
return boost::report_errors();
}

View File

@@ -0,0 +1,156 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2015
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include "itestvalue.hpp"
#include "bptr_value.hpp"
#include "smart_ptr.hpp"
#include "bs_test_common.hpp"
#include "generic_set_test.hpp"
#include <boost/intrusive/treap_set.hpp>
using namespace boost::intrusive;
template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Map >
struct rebinder
{
typedef tree_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type;
template < class Option1 =void
, class Option2 =void
>
struct container
{
typedef treap_set
< typename common_t::value_type
, value_traits<ValueTraits>
, constant_time_size<ConstantTimeSize>
, typename common_t::holder_opt
, typename common_t::key_of_value_opt
, typename common_t::prio_of_value_opt
, Option1
, Option2
> type;
BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value));
};
};
enum HookType
{
Base,
Member,
NonMember
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type>
class test_main_template;
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//base
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::base_value_traits
, typename testval_traits_t::auto_base_value_traits
>::type base_hook_t;
test::test_generic_set
< rebinder<base_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//member
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::member_value_traits
, typename testval_traits_t::auto_member_value_traits
>::type member_hook_t;
test::test_generic_set
< rebinder<member_hook_t, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember>
{
public:
static void execute()
{
typedef testvalue_traits< bs_hooks<VoidPointer> > testval_traits_t;
//nonmember
test::test_generic_set
< rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, DefaultHolder, Map>
>::test_all();
}
};
template < bool ConstantTimeSize, bool Map >
struct test_main_template_bptr
{
static void execute()
{
typedef BPtr_Value_Traits< Tree_BPtr_Node_Traits > value_traits;
typedef bounded_allocator< BPtr_Value > allocator_type;
bounded_allocator_scope<allocator_type> bounded_scope; (void)bounded_scope;
test::test_generic_set
< rebinder< value_traits, ConstantTimeSize, true, Map>
>::test_all();
}
};
int main()
{
//Combinations: VoidPointer x ConstantTimeSize x DefaultHolder x Map
//Minimize them selecting different combinations for raw and smart pointers
//Start with ('false', 'false', 'false') in sets and 'false', 'false', 'true' in multisets
//void pointer
test_main_template<void*, false, false, false, Base>::execute();
//test_main_template<void*, false, false, true>::execute();
test_main_template<void*, false, true, false, Member>::execute();
//test_main_template<void*, false, true, true>::execute();
test_main_template<void*, true, false, false, Base>::execute();
//test_main_template<void*, true, false, true>::execute();
test_main_template<void*, true, true, false, Member>::execute();
test_main_template<void*, true, true, true, NonMember>::execute();
//smart_ptr
//test_main_template<smart_ptr<void>, false, false, false>::execute();
test_main_template<smart_ptr<void>, false, false, true, Base>::execute();
//test_main_template<smart_ptr<void>, false, true, false>::execute();
test_main_template<smart_ptr<void>, false, true, true, Member>::execute();
//test_main_template<smart_ptr<void>, true, false, false>::execute();
test_main_template<smart_ptr<void>, true, false, true, NonMember>::execute();
//test_main_template<smart_ptr<void>, true, true, false>::execute();
//test_main_template<smart_ptr<void>, true, true, true>::execute();
//bounded_ptr (bool ConstantTimeSize, bool Map)
test_main_template_bptr< false, false >::execute();
//test_main_template_bptr< false, true >::execute();
//test_main_template_bptr< true, false >::execute();
test_main_template_bptr< true, true >::execute();
return boost::report_errors();
}

View File

@@ -0,0 +1,167 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2015.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/unordered_set.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/iterator.hpp>
#include "itestvalue.hpp"
#include "smart_ptr.hpp"
#include "common_functors.hpp"
#include <vector>
#include <algorithm> //std::sort
#include <set>
#include <boost/core/lightweight_test.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
#include "unordered_test_common.hpp"
#include "unordered_test.hpp"
using namespace boost::intrusive;
template < class ValueTraits, bool ConstantTimeSize, bool CacheBegin, bool CompareHash, bool Incremental, bool Map, bool DefaultHolder >
struct rebinder
{
typedef unordered_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type;
template < class Option1 =void
, class Option2 =void
>
struct container
{
typedef unordered_multiset
< typename common_t::value_type
, value_traits<ValueTraits>
, constant_time_size<ConstantTimeSize>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
, typename common_t::holder_opt
, typename common_t::key_of_value_opt
, Option1
, Option2
> type;
BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value));
BOOST_STATIC_ASSERT((boost::intrusive::test::is_multikey_true<type>::value));
};
};
enum HookType
{
Base,
Member,
NonMember
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type>
class test_main_template;
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base>
{
public:
static void execute()
{
typedef testvalue<unordered_hooks<VoidPointer> > value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
typedef typename ValueContainer< value_type >::type value_cont_type;
value_cont_type data (6);
for (std::size_t i = 0u; i < 6u; ++i)
data[i].value_ = random_init[i];
typedef testvalue_traits< unordered_hooks<VoidPointer> > testval_traits_t;
//base
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::base_value_traits
, typename testval_traits_t::auto_base_value_traits //store_hash<true>
>::type base_hook_t;
test::test_unordered
< //cache_begin, compare_hash, incremental
rebinder<base_hook_t, ConstantTimeSize, ConstantTimeSize, !ConstantTimeSize, !!ConstantTimeSize, Map, DefaultHolder>
>::test_all(data);
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member>
{
public:
static void execute()
{
typedef testvalue<unordered_hooks<VoidPointer> > value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
typedef typename ValueContainer< value_type >::type value_cont_type;
value_cont_type data (6);
for (std::size_t i = 0u; i < 6u; ++i)
data[i].value_ = random_init[i];
typedef testvalue_traits< unordered_hooks<VoidPointer> > testval_traits_t;
//member
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::member_value_traits //optimize_multikey<true>
, typename testval_traits_t::auto_member_value_traits //store_hash<true>, optimize_multikey<true>
>::type member_hook_t;
test::test_unordered
< //cache_begin, compare_hash, incremental
rebinder<member_hook_t, ConstantTimeSize, false, !ConstantTimeSize, false, !ConstantTimeSize, DefaultHolder>
>::test_all(data);
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember>
{
public:
static void execute()
{
typedef testvalue<unordered_hooks<VoidPointer> > value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
typedef typename ValueContainer< value_type >::type value_cont_type;
value_cont_type data (6);
for (std::size_t i = 0; i < 6u; ++i)
data[i].value_ = random_init[i];
typedef testvalue_traits< unordered_hooks<VoidPointer> > testval_traits_t;
//nonmember
test::test_unordered
< //cache_begin, compare_hash, incremental
rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, false, false, false, Map, DefaultHolder>
>::test_all(data);
}
};
int main()
{
//VoidPointer x ConstantTimeSize x Map x DefaultHolder
//void pointer
test_main_template<void*, false, false, false, Base>::execute();
test_main_template<void*, false, true, false, Member>::execute();
test_main_template<void*, true, false, false, NonMember>::execute();
test_main_template<void*, true, true, false, Base>::execute();
//smart_ptr
test_main_template<smart_ptr<void>, false, false, false, Member>::execute();
test_main_template<smart_ptr<void>, false, true, false, NonMember>::execute();
test_main_template<smart_ptr<void>, true, false, false, Base>::execute();
test_main_template<smart_ptr<void>, true, true, false, Member>::execute();
////bounded_ptr (bool ConstantTimeSize, bool Map)
//test_main_template_bptr< false, false >::execute();
//test_main_template_bptr< false, true >::execute();
//test_main_template_bptr< true, false >::execute();
//test_main_template_bptr< true, true >::execute();
return boost::report_errors();
}

View File

@@ -0,0 +1,167 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2015.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/unordered_set.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/iterator.hpp>
#include "itestvalue.hpp"
#include "smart_ptr.hpp"
#include "common_functors.hpp"
#include <vector>
#include <set>
#include <boost/core/lightweight_test.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
#include "unordered_test_common.hpp"
#include "unordered_test.hpp"
using namespace boost::intrusive;
template < class ValueTraits, bool ConstantTimeSize, bool CacheBegin, bool CompareHash, bool Incremental, bool Map, bool DefaultHolder >
struct rebinder
{
typedef unordered_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type;
template < class Option1 =void
, class Option2 =void
>
struct container
{
typedef unordered_set
< typename common_t::value_type
, value_traits<ValueTraits>
, constant_time_size<ConstantTimeSize>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
, typename common_t::holder_opt
, typename common_t::key_of_value_opt
, size_type<unsigned short>
, Option1
, Option2
> type;
BOOST_STATIC_ASSERT((key_type_tester<typename common_t::key_of_value_opt, type>::value));
BOOST_STATIC_ASSERT((!boost::intrusive::test::is_multikey_true<type>::value));
};
};
enum HookType
{
Base,
Member,
NonMember
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type>
class test_main_template;
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base>
{
public:
static void execute()
{
typedef testvalue<unordered_hooks<VoidPointer> > value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
typedef typename ValueContainer< value_type >::type value_cont_type;
value_cont_type data (6);
for (std::size_t i = 0; i < 6u; ++i)
data[i].value_ = random_init[i];
typedef testvalue_traits< unordered_hooks<VoidPointer> > testval_traits_t;
//base
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::base_value_traits
, typename testval_traits_t::auto_base_value_traits //store_hash<true>
>::type base_hook_t;
test::test_unordered
< //cache_begin, compare_hash, incremental
rebinder<base_hook_t, ConstantTimeSize, ConstantTimeSize, !ConstantTimeSize, !!ConstantTimeSize, Map, DefaultHolder>
>::test_all(data);
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member>
{
public:
static void execute()
{
typedef testvalue<unordered_hooks<VoidPointer> > value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
typedef typename ValueContainer< value_type >::type value_cont_type;
value_cont_type data (6);
for (std::size_t i = 0; i < 6u; ++i)
data[i].value_ = random_init[i];
typedef testvalue_traits< unordered_hooks<VoidPointer> > testval_traits_t;
//member
typedef typename detail::if_c
< ConstantTimeSize
, typename testval_traits_t::member_value_traits //optimize_multikey<true>
, typename testval_traits_t::auto_member_value_traits //store_hash<true>, optimize_multikey<true>
>::type member_hook_t;
test::test_unordered
< //cache_begin, compare_hash, incremental
rebinder<member_hook_t, ConstantTimeSize, false, !ConstantTimeSize, false, !ConstantTimeSize, DefaultHolder>
>::test_all(data);
}
};
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember>
{
public:
static void execute()
{
typedef testvalue<unordered_hooks<VoidPointer> > value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
typedef typename ValueContainer< value_type >::type value_cont_type;
value_cont_type data (6);
for (std::size_t i = 0; i < 6u; ++i)
data[i].value_ = random_init[i];
typedef testvalue_traits< unordered_hooks<VoidPointer> > testval_traits_t;
//nonmember
test::test_unordered
< //cache_begin, compare_hash, incremental
rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, false, false, false, Map, DefaultHolder>
>::test_all(data);
}
};
int main()
{
//VoidPointer x ConstantTimeSize x Map x DefaultHolder
//void pointer
test_main_template<void*, false, false, false, Base>::execute();
test_main_template<void*, false, true, false, Member>::execute();
test_main_template<void*, true, false, false, NonMember>::execute();
test_main_template<void*, true, true, false, Base>::execute();
//smart_ptr
test_main_template<smart_ptr<void>, false, false, false, Member>::execute();
test_main_template<smart_ptr<void>, false, true, false, NonMember>::execute();
test_main_template<smart_ptr<void>, true, false, false, Base>::execute();
test_main_template<smart_ptr<void>, true, true, false, Member>::execute();
////bounded_ptr (bool ConstantTimeSize, bool Map)
//test_main_template_bptr< false, false >::execute();
//test_main_template_bptr< false, true >::execute();
//test_main_template_bptr< true, false >::execute();
//test_main_template_bptr< true, true >::execute();
return boost::report_errors();
}

View File

@@ -0,0 +1,751 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/iterator.hpp>
#include "common_functors.hpp"
#include <vector>
#include <algorithm> //std::sort
#include <set>
#include <boost/core/lightweight_test.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
#include "unordered_test_common.hpp"
namespace boost{
namespace intrusive{
namespace test{
static const std::size_t BucketSize = 8;
template<class ContainerDefiner>
struct test_unordered
{
typedef typename ContainerDefiner::value_cont_type value_cont_type;
static void test_all(value_cont_type& values);
private:
static void test_sort(value_cont_type& values);
static void test_insert(value_cont_type& values, detail::true_);
static void test_insert(value_cont_type& values, detail::false_);
static void test_swap(value_cont_type& values);
static void test_rehash(value_cont_type& values, detail::true_);
static void test_rehash(value_cont_type& values, detail::false_);
static void test_find(value_cont_type& values);
static void test_impl();
static void test_clone(value_cont_type& values);
};
template<class ContainerDefiner>
void test_unordered<ContainerDefiner>::test_all (value_cont_type& values)
{
typedef typename ContainerDefiner::template container
<>::type unordered_type;
typedef typename unordered_type::bucket_traits bucket_traits;
typedef typename unordered_type::bucket_ptr bucket_ptr;
{
typename unordered_type::bucket_type buckets [BucketSize];
unordered_type testset
(bucket_traits(pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize));
testset.insert(values.begin(), values.end());
test::test_container(testset);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_common_unordered_and_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_unordered_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
typedef detail::bool_<boost::intrusive::test::is_multikey_true
<unordered_type>::value> select_t;
test::test_maybe_unique_container(testset, values, select_t());
}
{
value_cont_type vals(BucketSize);
for (std::size_t i = 0; i < BucketSize; ++i)
(&vals[i])->value_ = (int)i;
typename unordered_type::bucket_type buckets [BucketSize];
unordered_type testset(bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize));
testset.insert(vals.begin(), vals.end());
test::test_iterator_forward(testset);
}
test_sort(values);
test_insert(values, detail::bool_<boost::intrusive::test::is_multikey_true<unordered_type>::value>());
test_swap(values);
test_rehash(values, detail::bool_<unordered_type::incremental>());
test_find(values);
test_impl();
test_clone(values);
}
//test case due to an error in tree implementation:
template<class ContainerDefiner>
void test_unordered<ContainerDefiner>::test_impl()
{
typedef typename ContainerDefiner::template container
<>::type unordered_type;
typedef typename unordered_type::bucket_traits bucket_traits;
typedef typename unordered_type::bucket_ptr bucket_ptr;
value_cont_type values (5);
for (std::size_t i = 0u; i < 5u; ++i)
values[i].value_ = (int)i;
typename unordered_type::bucket_type buckets [BucketSize];
unordered_type testset(bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize));
for (std::size_t i = 0u; i < 5u; ++i)
testset.insert (values[i]);
testset.erase (testset.iterator_to (values[0]));
testset.erase (testset.iterator_to (values[1]));
testset.insert (values[1]);
testset.erase (testset.iterator_to (values[2]));
testset.erase (testset.iterator_to (values[3]));
}
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
template<class ContainerDefiner>
void test_unordered<ContainerDefiner>::test_sort(value_cont_type& values)
{
typedef typename ContainerDefiner::template container
<>::type unordered_type;
typedef typename unordered_type::bucket_traits bucket_traits;
typedef typename unordered_type::bucket_ptr bucket_ptr;
typename unordered_type::bucket_type buckets [BucketSize];
unordered_type testset1
(values.begin(), values.end(), bucket_traits
(pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize));
if(unordered_type::incremental){
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
}
else{
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
}
testset1.clear();
BOOST_TEST (testset1.empty());
}
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
template<class ContainerDefiner>
void test_unordered<ContainerDefiner>::test_insert(value_cont_type& values, detail::false_) //not multikey
{
typedef typename ContainerDefiner::template container
<>::type unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
typedef typename unordered_set_type::key_of_value key_of_value;
typename unordered_set_type::bucket_type buckets [BucketSize];
unordered_set_type testset(bucket_traits(
pointer_traits<typename unordered_set_type::bucket_ptr>::
pointer_to(buckets[0]), BucketSize));
testset.insert(&values[0] + 2, &values[0] + 5);
typename unordered_set_type::insert_commit_data commit_data;
BOOST_TEST ((!testset.insert_check(key_of_value()(values[2]), commit_data).second));
BOOST_TEST (( testset.insert_check(key_of_value()(values[0]), commit_data).second));
const unordered_set_type& const_testset = testset;
if(unordered_set_type::incremental)
{
{ int init_values [] = { 4, 5, 1 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); }
typename unordered_set_type::iterator i = testset.begin();
BOOST_TEST (i->value_ == 4);
i = testset.insert(values[0]).first;
BOOST_TEST (&*i == &values[0]);
i = testset.iterator_to (values[2]);
BOOST_TEST (&*i == &values[2]);
testset.erase (i);
{ int init_values [] = { 5, 1, 3 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); }
}
else{
{ int init_values [] = { 1, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); }
typename unordered_set_type::iterator i = testset.begin();
BOOST_TEST (i->value_ == 1);
i = testset.insert(values[0]).first;
BOOST_TEST (&*i == &values[0]);
i = testset.iterator_to (values[2]);
BOOST_TEST (&*i == &values[2]);
testset.erase (i);
{ int init_values [] = { 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); }
}
}
template<class ContainerDefiner>
void test_unordered<ContainerDefiner>::test_insert(value_cont_type& values, detail::true_) //is multikey
{
typedef typename ContainerDefiner::template container
<>::type unordered_type;
typedef typename unordered_type::bucket_traits bucket_traits;
typedef typename unordered_type::bucket_ptr bucket_ptr;
typedef typename unordered_type::iterator iterator;
typedef typename unordered_type::key_type key_type;
{
typename unordered_type::bucket_type buckets [BucketSize];
unordered_type testset(bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize));
testset.insert(&values[0] + 2, &values[0] + 5);
const unordered_type& const_testset = testset;
if(unordered_type::incremental){
{
{ int init_values [] = { 4, 5, 1 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); }
typename unordered_type::iterator i = testset.begin();
BOOST_TEST (i->value_ == 4);
i = testset.insert (values[0]);
BOOST_TEST (&*i == &values[0]);
i = testset.iterator_to (values[2]);
BOOST_TEST (&*i == &values[2]);
testset.erase(i);
{ int init_values [] = { 5, 1, 3 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); }
testset.clear();
testset.insert(&values[0], &values[0] + values.size());
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); }
BOOST_TEST (testset.erase(key_type(1)) == 1);
BOOST_TEST (testset.erase(key_type(2)) == 2);
BOOST_TEST (testset.erase(key_type(3)) == 1);
BOOST_TEST (testset.erase(key_type(4)) == 1);
BOOST_TEST (testset.erase(key_type(5)) == 1);
BOOST_TEST (testset.empty() == true);
//Now with a single bucket
typename unordered_type::bucket_type single_bucket[1];
unordered_type testset2(bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(single_bucket[0]), 1));
testset2.insert(&values[0], &values[0] + values.size());
BOOST_TEST (testset2.erase(key_type(5)) == 1);
BOOST_TEST (testset2.erase(key_type(2)) == 2);
BOOST_TEST (testset2.erase(key_type(1)) == 1);
BOOST_TEST (testset2.erase(key_type(4)) == 1);
BOOST_TEST (testset2.erase(key_type(3)) == 1);
BOOST_TEST (testset2.empty() == true);
}
}
else{
{
{ int init_values [] = { 1, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); }
typename unordered_type::iterator i = testset.begin();
BOOST_TEST (i->value_ == 1);
i = testset.insert (values[0]);
BOOST_TEST (&*i == &values[0]);
i = testset.iterator_to (values[2]);
BOOST_TEST (&*i == &values[2]);
testset.erase(i);
{ int init_values [] = { 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); }
testset.clear();
testset.insert(&values[0], &values[0] + values.size());
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, const_testset ); }
BOOST_TEST (testset.erase(key_type(1)) == 1);
BOOST_TEST (testset.erase(key_type(2)) == 2);
BOOST_TEST (testset.erase(key_type(3)) == 1);
BOOST_TEST (testset.erase(key_type(4)) == 1);
BOOST_TEST (testset.erase(key_type(5)) == 1);
BOOST_TEST (testset.empty() == true);
//Now with a single bucket
typename unordered_type::bucket_type single_bucket[1];
unordered_type testset2(bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(single_bucket[0]), 1));
testset2.insert(&values[0], &values[0] + values.size());
BOOST_TEST (testset2.erase(key_type(5)) == 1);
BOOST_TEST (testset2.erase(key_type(2)) == 2);
BOOST_TEST (testset2.erase(key_type(1)) == 1);
BOOST_TEST (testset2.erase(key_type(4)) == 1);
BOOST_TEST (testset2.erase(key_type(3)) == 1);
BOOST_TEST (testset2.empty() == true);
}
}
{
//Now erase just one per loop
const int random_init[] = { 3, 2, 4, 1, 5, 2, 2 };
const std::size_t random_size = sizeof(random_init)/sizeof(random_init[0]);
typename unordered_type::bucket_type single_bucket[1];
for(std::size_t i = 0u, max = random_size; i != max; ++i){
value_cont_type data (random_size);
for (std::size_t j = 0; j < random_size; ++j)
data[j].value_ = random_init[j];
unordered_type testset_new(bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(single_bucket[0]), 1));
testset_new.insert(&data[0], &data[0]+max);
testset_new.erase(testset_new.iterator_to(data[i]));
BOOST_TEST (testset_new.size() == (max -1));
}
}
}
{
const std::size_t LoadFactor = 3;
const std::size_t NumIterations = BucketSize*LoadFactor;
value_cont_type random_init(NumIterations);//Preserve memory
value_cont_type set_tester;
set_tester.reserve(NumIterations);
//Initialize values
for (std::size_t i = 0u; i < NumIterations; ++i){
random_init[i].value_ = (int)i*2;//(i/LoadFactor)*LoadFactor;
}
typename unordered_type::bucket_type buckets [BucketSize];
bucket_traits btraits(pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize);
for(std::size_t initial_pos = 0; initial_pos != (NumIterations+1u); ++initial_pos){
for(std::size_t final_pos = initial_pos; final_pos != (NumIterations+1); ++final_pos){
//Create intrusive container inserting values
unordered_type testset
( random_init.data()
, random_init.data() + random_init.size()
, btraits);
BOOST_TEST (testset.size() == random_init.size());
//Obtain the iterator range to erase
iterator it_beg_pos = testset.begin();
for(std::size_t 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(std::size_t 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_udistance(it_beg_pos, it_end_pos);
//Erase values from the intrusive container
testset.erase(it_beg_pos, it_end_pos);
BOOST_TEST (testset.size() == (random_init.size()-(final_pos - initial_pos)));
//Now test...
BOOST_TEST ((random_init.size() - erased_cnt) == testset.size());
//Create an ordered copy of the intrusive container
set_tester.insert(set_tester.end(), testset.begin(), testset.end());
std::sort(set_tester.begin(), set_tester.end());
{
typename value_cont_type::iterator it = set_tester.begin(), itend = set_tester.end();
typename value_cont_type::iterator random_init_it(random_init.begin());
for( ; it != itend; ++it){
while(!random_init_it->is_linked())
++random_init_it;
BOOST_TEST(*it == *random_init_it);
++random_init_it;
}
}
set_tester.clear();
}
}
}
}
//test: insert (seq-version), swap, erase (seq-version), size:
template<class ContainerDefiner>
void test_unordered<ContainerDefiner>::test_swap(value_cont_type& values)
{
typedef typename ContainerDefiner::template container
<>::type unordered_type;
typedef typename unordered_type::bucket_traits bucket_traits;
typedef typename unordered_type::bucket_ptr bucket_ptr;
typename unordered_type::bucket_type buckets [BucketSize];
typename unordered_type::bucket_type buckets2 [BucketSize];
unordered_type testset1(&values[0], &values[0] + 2,
bucket_traits(pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize));
unordered_type testset2(bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), BucketSize));
testset2.insert (&values[0] + 2, &values[0] + 6);
testset1.swap (testset2);
if(unordered_type::incremental){
{ int init_values [] = { 4, 5, 1, 2 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
{ int init_values [] = { 2, 3 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset2 ); }
testset1.erase (testset1.iterator_to(values[4]), testset1.end());
BOOST_TEST (testset1.size() == 1);
// BOOST_TEST (&testset1.front() == &values[3]);
BOOST_TEST (&*testset1.begin() == &values[2]);
}
else{
{ int init_values [] = { 1, 2, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
{ int init_values [] = { 2, 3 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset2 ); }
testset1.erase (testset1.iterator_to(values[5]), testset1.end());
BOOST_TEST (testset1.size() == 1);
// BOOST_TEST (&testset1.front() == &values[3]);
BOOST_TEST (&*testset1.begin() == &values[3]);
}
}
//test: rehash:
template<class ContainerDefiner>
void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, detail::true_)
{
typedef typename ContainerDefiner::template container
<>::type unordered_type;
typedef typename unordered_type::bucket_traits bucket_traits;
typedef typename unordered_type::bucket_ptr bucket_ptr;
//Build a uset
typename unordered_type::bucket_type buckets1 [BucketSize];
typename unordered_type::bucket_type buckets2 [BucketSize*2];
unordered_type testset1(&values[0], &values[0] + values.size(),
bucket_traits(pointer_traits<bucket_ptr>::
pointer_to(buckets1[0]), BucketSize));
//Test current state
BOOST_TEST(testset1.split_count() == BucketSize/2);
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
//Incremental rehash step
BOOST_TEST (testset1.incremental_rehash() == true);
BOOST_TEST(testset1.split_count() == (BucketSize/2+1));
{ int init_values [] = { 5, 1, 2, 2, 3, 4 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
//Rest of incremental rehashes should lead to the same sequence
for(std::size_t split_bucket = testset1.split_count(); split_bucket != BucketSize; ++split_bucket){
BOOST_TEST (testset1.incremental_rehash() == true);
BOOST_TEST(testset1.split_count() == (split_bucket+1));
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
}
//This incremental rehash should fail because we've reached the end of the bucket array
BOOST_TEST (testset1.incremental_rehash() == false);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
//
//Try incremental hashing specifying a new bucket traits pointing to the same array
//
//This incremental rehash should fail because the new size is not twice the original
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
pointer_traits<bucket_ptr>::
pointer_to(buckets1[0]), BucketSize)) == false);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
//
//Try incremental hashing specifying a new bucket traits pointing to the same array
//
//This incremental rehash should fail because the new size is not twice the original
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
pointer_traits<bucket_ptr>::
pointer_to(buckets2[0]), BucketSize)) == false);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
//This incremental rehash should success because the new size is twice the original
//and split_count is the same as the old bucket count
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
pointer_traits<bucket_ptr>::
pointer_to(buckets2[0]), BucketSize*2)) == true);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
//This incremental rehash should also success because the new size is half the original
//and split_count is the same as the new bucket count
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
pointer_traits<bucket_ptr>::
pointer_to(buckets1[0]), BucketSize)) == true);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
//Shrink rehash
testset1.rehash(bucket_traits(
pointer_traits<bucket_ptr>::
pointer_to(buckets1[0]), 4));
BOOST_TEST (testset1.incremental_rehash() == false);
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
//Shrink rehash again
testset1.rehash(bucket_traits(
pointer_traits<bucket_ptr>::
pointer_to(buckets1[0]), 2));
BOOST_TEST (testset1.incremental_rehash() == false);
{ int init_values [] = { 2, 2, 4, 3, 5, 1 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
//Growing rehash
testset1.rehash(bucket_traits(
pointer_traits<bucket_ptr>::
pointer_to(buckets1[0]), BucketSize));
//Full rehash (no effects)
testset1.full_rehash();
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
//Incremental rehash shrinking
//First incremental rehashes should lead to the same sequence
for(std::size_t split_bucket = testset1.split_count(); split_bucket > 6; --split_bucket){
BOOST_TEST (testset1.incremental_rehash(false) == true);
BOOST_TEST(testset1.split_count() == (split_bucket-1));
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
}
//Incremental rehash step
BOOST_TEST (testset1.incremental_rehash(false) == true);
BOOST_TEST(testset1.split_count() == (BucketSize/2+1));
{ int init_values [] = { 5, 1, 2, 2, 3, 4 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
//Incremental rehash step 2
BOOST_TEST (testset1.incremental_rehash(false) == true);
BOOST_TEST(testset1.split_count() == (BucketSize/2));
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
//This incremental rehash should fail because we've reached the half of the bucket array
BOOST_TEST(testset1.incremental_rehash(false) == false);
BOOST_TEST(testset1.split_count() == BucketSize/2);
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
}
template<class ContainerDefiner>
void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, detail::false_)
{
typedef typename ContainerDefiner::template container
<>::type unordered_type;
typedef typename unordered_type::bucket_traits bucket_traits;
typedef typename unordered_type::bucket_ptr bucket_ptr;
typename unordered_type::bucket_type buckets1 [BucketSize];
typename unordered_type::bucket_type buckets2 [2];
typename unordered_type::bucket_type buckets3 [BucketSize*2];
unordered_type testset1(&values[0], &values[0] + 6, bucket_traits(
pointer_traits<bucket_ptr>::
pointer_to(buckets1[0]), BucketSize));
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
testset1.rehash(bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), 2));
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
testset1.rehash(bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(buckets3[0]), BucketSize*2));
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
//Now rehash reducing the buckets
testset1.rehash(bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(buckets3[0]), 2));
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
//Now rehash increasing the buckets
testset1.rehash(bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(buckets3[0]), BucketSize*2));
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
//Full rehash (no effects)
testset1.full_rehash();
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
}
//test: find, equal_range (lower_bound, upper_bound):
template<class ContainerDefiner>
void test_unordered<ContainerDefiner>::test_find(value_cont_type& values)
{
typedef typename ContainerDefiner::template container
<>::type unordered_type;
typedef typename unordered_type::value_type value_type;
typedef typename unordered_type::bucket_traits bucket_traits;
typedef typename unordered_type::bucket_ptr bucket_ptr;
typedef typename unordered_type::key_of_value key_of_value;
const bool is_multikey = boost::intrusive::test::is_multikey_true<unordered_type>::value;
typename unordered_type::bucket_type buckets[BucketSize];
unordered_type testset(values.begin(), values.end(), bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize));
typedef typename unordered_type::iterator iterator;
value_type cmp_val;
cmp_val.value_ = 2;
BOOST_TEST (testset.count(key_of_value()(cmp_val)) == (is_multikey ? 2 : 1));
iterator i = testset.find (key_of_value()(cmp_val));
BOOST_TEST (i->value_ == 2);
if(is_multikey)
BOOST_TEST ((++i)->value_ == 2);
else
BOOST_TEST ((++i)->value_ != 2);
std::pair<iterator,iterator> range = testset.equal_range (key_of_value()(cmp_val));
BOOST_TEST (range.first->value_ == 2);
BOOST_TEST (range.second->value_ == 3);
BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == (is_multikey ? 2 : 1));
cmp_val.value_ = 7;
BOOST_TEST (testset.find (key_of_value()(cmp_val)) == testset.end());
BOOST_TEST (testset.count(key_of_value()(cmp_val)) == 0);
}
template<class ContainerDefiner>
void test_unordered<ContainerDefiner>::test_clone(value_cont_type& values)
{
typedef typename ContainerDefiner::template container
<>::type unordered_type;
typedef typename unordered_type::value_type value_type;
typedef std::multiset<value_type> std_multiset_t;
typedef typename unordered_type::bucket_traits bucket_traits;
typedef typename unordered_type::bucket_ptr bucket_ptr;
{
//Test with equal bucket arrays
typename unordered_type::bucket_type buckets1 [BucketSize];
typename unordered_type::bucket_type buckets2 [BucketSize];
unordered_type testset1 (values.begin(), values.end(), bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(buckets1[0]), BucketSize));
unordered_type testset2 (bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), BucketSize));
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
BOOST_TEST(testset1 == testset2);
//Ordering is not guarantee in the cloning so insert data in a set and test
std_multiset_t src(testset1.begin(), testset1.end());
std_multiset_t dst(testset2.begin(), testset2.end());
BOOST_TEST (src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin()));
testset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testset2.empty());
testset2.clone_from(boost::move(testset1), test::new_nonconst_cloner<value_type>(), test::delete_disposer<value_type>());
BOOST_TEST(testset1 == testset2);
//Ordering is not guarantee in the cloning so insert data in a set and test
std_multiset_t(testset1.begin(), testset1.end()).swap(src);
std_multiset_t(testset2.begin(), testset2.end()).swap(dst);
BOOST_TEST(src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin()));
testset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testset2.empty());
}
{
//Test with bigger source bucket arrays
typename unordered_type::bucket_type buckets1 [BucketSize*2];
typename unordered_type::bucket_type buckets2 [BucketSize];
unordered_type testset1 (values.begin(), values.end(), bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(buckets1[0]), BucketSize*2));
unordered_type testset2 (bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), BucketSize));
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
BOOST_TEST(testset1 == testset2);
//Ordering is not guarantee in the cloning so insert data in a set and test
std_multiset_t src(testset1.begin(), testset1.end());
std_multiset_t dst(testset2.begin(), testset2.end());
BOOST_TEST (src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin()));
testset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testset2.empty());
testset2.clone_from(boost::move(testset1), test::new_nonconst_cloner<value_type>(), test::delete_disposer<value_type>());
BOOST_TEST(testset1 == testset2);
//Ordering is not guarantee in the cloning so insert data in a set and test
std_multiset_t(testset1.begin(), testset1.end()).swap(src);
std_multiset_t(testset2.begin(), testset2.end()).swap(dst);
BOOST_TEST (src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin()));
testset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testset2.empty());
}
{
//Test with smaller source bucket arrays
typename unordered_type::bucket_type buckets1 [BucketSize];
typename unordered_type::bucket_type buckets2 [BucketSize*2];
unordered_type testset1 (values.begin(), values.end(), bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(buckets1[0]), BucketSize));
unordered_type testset2 (bucket_traits(
pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), BucketSize*2));
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
BOOST_TEST(testset1 == testset2);
//Ordering is not guaranteed in the cloning so insert data in a set and test
std_multiset_t src(testset1.begin(), testset1.end());
std_multiset_t dst(testset2.begin(), testset2.end());
BOOST_TEST (src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin()));
testset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testset2.empty());
testset2.clone_from(boost::move(testset1), test::new_nonconst_cloner<value_type>(), test::delete_disposer<value_type>());
BOOST_TEST(testset1 == testset2);
//Ordering is not guaranteed in the cloning so insert data in a set and test
std_multiset_t(testset1.begin(), testset1.end()).swap(src);
std_multiset_t(testset2.begin(), testset2.end()).swap(dst);
BOOST_TEST (src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin()));
testset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testset2.empty());
}
}
} //namespace test{
} //namespace intrusive{
} //namespace boost{

View File

@@ -0,0 +1,69 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_TEST_UNORDERED_TEST_COMMON_HPP
#define BOOST_INTRUSIVE_TEST_UNORDERED_TEST_COMMON_HPP
#include <boost/intrusive/unordered_set_hook.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include "bptr_value.hpp"
#include "test_common.hpp"
namespace boost {
namespace intrusive {
template<class VoidPointer>
struct unordered_hooks
{
typedef unordered_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
typedef unordered_set_base_hook
< link_mode<auto_unlink>
, void_pointer<VoidPointer>
, tag<void>
, store_hash<true>
> auto_base_hook_type;
typedef unordered_set_member_hook
< void_pointer<VoidPointer>
, optimize_multikey<true>
> member_hook_type;
typedef unordered_set_member_hook
< link_mode<auto_unlink>, void_pointer<VoidPointer>
, store_hash<true>
, optimize_multikey<true>
> auto_member_hook_type;
typedef nonhook_node_member< unordered_node_traits< VoidPointer, true, true >,
unordered_algorithms
> nonhook_node_member_type;
};
template < class ValueTraits, bool DefaultHolder, bool Map >
struct unordered_rebinder_common
{
typedef typename ValueTraits::value_type value_type;
typedef typename detail::if_c
< DefaultHolder
, typename detail::if_c
< detail::is_same<value_type, BPtr_Value>::value
, header_holder_type< bounded_pointer_holder< BPtr_Value > >
, void
>::type
, header_holder_type< heap_node_holder< typename ValueTraits::node_ptr > >
>::type holder_opt;
typedef typename detail::if_c
< Map, key_of_value<int_holder_key_of_value<value_type> >, void
>::type key_of_value_opt;
};
} //namespace intrusive {
} //namespace boost {
#endif //BOOST_INTRUSIVE_TEST_UNORDERED_TEST_COMMON_HPP

View File

@@ -0,0 +1,100 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <vector>
using namespace boost::intrusive;
struct VirtualBase
{
virtual ~VirtualBase(){}
};
struct VirtualBase2
{
virtual ~VirtualBase2(){}
};
struct VirtualBase3
{
};
class NonVirtualBase
: public virtual VirtualBase
, public virtual VirtualBase2
{
protected:
NonVirtualBase()
: dummy()
{}
//<-
const int *get_dummy() const { return dummy; }
//->
private:
int dummy[10];
};
class MyClass
: public NonVirtualBase
, public virtual VirtualBase3
{
int int_;
public:
list_member_hook<> list_hook_;
MyClass(int i = 0)
: int_(i)
{}
//<-
int get_int() const { return int_; }
//->
};
//Define a list that will store MyClass using the public base hook
typedef member_hook< MyClass, list_member_hook<>, &MyClass::list_hook_ > MemberHook;
typedef list<MyClass, MemberHook> List;
int main()
{
#ifndef _MSC_VER
typedef std::vector<MyClass>::iterator VectIt;
typedef std::vector<MyClass>::reverse_iterator VectRit;
//Create several MyClass objects, each one with a different value
std::vector<MyClass> values;
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
List my_list;
//Now insert them in the reverse order
//in the base hook intrusive list
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
my_list.push_front(*it);
//Now test lists
{
List::const_iterator list_it(my_list.cbegin());
VectRit vect_it(values.rbegin()), vect_itend(values.rend());
//Test the objects inserted in the base hook list
for(; vect_it != vect_itend; ++vect_it, ++list_it)
if(&*list_it != &*vect_it)
return 1;
}
#endif
return 0;
}

View File

@@ -0,0 +1,94 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Andrey Semashev 2018.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/options.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/set_hook.hpp>
#include <boost/config.hpp>
#include <boost/core/lightweight_test.hpp>
#include <functional> // std::less
// The test verifies that the set implementation does not use void* as auxiliary arguments for SFINAE
// in internal functions, which would make overload resolution ambiguous if user's key type is also void*.
typedef boost::intrusive::set_base_hook<
boost::intrusive::link_mode< boost::intrusive::safe_link >,
boost::intrusive::tag< struct for_set_element_lookup_by_key >,
boost::intrusive::optimize_size< true >
> set_element_hook_t;
struct set_element :
public set_element_hook_t
{
struct order_by_key
{
typedef bool result_type;
result_type operator() (set_element const& left, set_element const& right) const
{
return std::less< void* >()(left.m_key, right.m_key);
}
result_type operator() (void* left, set_element const& right) const
{
return std::less< void* >()(left, right.m_key);
}
result_type operator() (set_element const& left, void* right) const
{
return std::less< void* >()(left.m_key, right);
}
};
void* m_key;
explicit set_element(void* key) : m_key(key) {}
BOOST_DELETED_FUNCTION(set_element(set_element const&))
BOOST_DELETED_FUNCTION(set_element& operator=(set_element const&))
};
typedef boost::intrusive::set<
set_element,
boost::intrusive::base_hook< set_element_hook_t >,
boost::intrusive::compare< set_element::order_by_key >,
boost::intrusive::constant_time_size< true >
> set_t;
void test_set()
{
int v1 = 0, v2 = 1, v3 = 2;
set_element e1(&v1), e2(&v2), e3(&v3);
set_t s;
s.insert(e1);
s.insert(e2);
set_t::iterator it = s.find(e1);
BOOST_TEST(it != s.end() && &*it == &e1);
it = s.find((void*)&v2, set_element::order_by_key());
BOOST_TEST(it != s.end() && &*it == &e2);
it = s.find(e3);
BOOST_TEST(it == s.end());
it = s.find((void*)&v3, set_element::order_by_key());
BOOST_TEST(it == s.end());
s.clear();
}
int main()
{
test_set();
return boost::report_errors();
}