pack_options is now public, documented and tested so that it can be used by other libraries like Container, to specify new options for customizable containers.

This commit is contained in:
Ion Gaztañaga
2013-12-29 13:42:55 +01:00
parent ada3266502
commit 37b30ef5c7
9 changed files with 638 additions and 497 deletions
+58 -495
View File
@@ -16,15 +16,15 @@
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/link_mode.hpp>
#include <boost/intrusive/pack_options.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/utilities.hpp>
#include <boost/static_assert.hpp>
namespace boost {
namespace intrusive {
/// @cond
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//typedef void default_tag;
struct default_tag;
@@ -34,8 +34,6 @@ namespace detail{
struct default_hook_tag{};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
#define BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER) \
struct BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER : public default_hook_tag\
{\
@@ -50,14 +48,9 @@ BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_rbtree_hook);
BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_hashtable_hook);
BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_avltree_hook);
BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_bstree_hook);
//BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_splaytree_hook);
//BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_sgtree_hook);
//BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_treap_hook);
#undef BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION
#endif //BOOST_INTRUSIVE_DOXYGEN_INVOKED
template <class ValueTraits>
struct eval_value_traits
{
@@ -165,7 +158,7 @@ struct get_value_traits
//...get it's internal value traits using
//the provided T value type.
, get_base_value_traits<T, supposed_value_traits>
//...else use it's internal value traits tag
//...else use its internal value traits tag
//(member hooks and custom value traits are in this group)
, detail::eval_if_c
< internal_member_value_traits<supposed_value_traits>::value
@@ -191,7 +184,7 @@ struct get_node_traits
//...get it's internal value traits using
//the provided T value type.
, get_base_node_traits<supposed_value_traits>
//...else use it's internal value traits tag
//...else use its internal value traits tag
//(member hooks and custom value traits are in this group)
, detail::eval_if_c
< internal_member_value_traits<supposed_value_traits>::value
@@ -203,50 +196,20 @@ struct get_node_traits
} //namespace detail{
/// @endcond
#endif //BOOST_INTRUSIVE_DOXYGEN_INVOKED
//!This option setter specifies if the intrusive
//!container stores its size as a member to
//!obtain constant-time size() member.
template<bool Enabled>
struct constant_time_size
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool constant_time_size = Enabled;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_CONSTANT(constant_time_size, bool, Enabled, constant_time_size)
//!This option setter specifies the type that
//!the container will use to store its size.
template<class SizeType>
struct size_type
{
/// @cond
template<class Base>
struct pack : Base
{
typedef SizeType size_type;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_TYPE(size_type, SizeType, SizeType, size_type)
//!This option setter specifies the strict weak ordering
//!comparison functor for the value type
template<class Compare>
struct compare
{
/// @cond
template<class Base>
struct pack : Base
{
typedef Compare compare;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_TYPE(compare, Compare, Compare, compare)
//!This option setter for scapegoat containers specifies if
//!the intrusive scapegoat container should use a non-variable
@@ -260,74 +223,39 @@ struct compare
//!If the user only needs an alpha value near 1/sqrt(2), this
//!option also improves performance since avoids logarithm
//!and division operations when rebalancing the tree.
template<bool Enabled>
struct floating_point
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool floating_point = Enabled;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_CONSTANT(floating_point, bool, Enabled, floating_point)
//!This option setter specifies the equality
//!functor for the value type
template<class Equal>
struct equal
{
/// @cond
template<class Base>
struct pack : Base
{
typedef Equal equal;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_TYPE(equal, Equal, Equal, equal)
//!This option setter specifies the equality
//!functor for the value type
template<class Priority>
struct priority
{
/// @cond
template<class Base>
struct pack : Base
{
typedef Priority priority;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_TYPE(priority, Priority, Priority, priority)
//!This option setter specifies the hash
//!functor for the value type
template<class Hash>
struct hash
{
/// @cond
template<class Base>
struct pack : Base
{
typedef Hash hash;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_TYPE(hash, Hash, Hash, hash)
//!This option setter specifies the relationship between the type
//!to be managed by the container (the value type) and the node to be
//!used in the node algorithms. It also specifies the linking policy.
template<typename ValueTraits>
struct value_traits
{
/// @cond
template<class Base>
struct pack : Base
{
typedef ValueTraits proto_value_traits;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_TYPE(value_traits, ValueTraits, ValueTraits, proto_value_traits)
//#define BOOST_INTRUSIVE_COMMA ,
//#define BOOST_INTRUSIVE_LESS <
//#define BOOST_INTRUSIVE_MORE >
//BOOST_INTRUSIVE_OPTION_TYPE (member_hook, Parent BOOST_INTRUSIVE_COMMA class MemberHook BOOST_INTRUSIVE_COMMA MemberHook Parent::* PtrToMember , mhtraits BOOST_INTRUSIVE_LESS Parent BOOST_INTRUSIVE_COMMA MemberHook BOOST_INTRUSIVE_COMMA PtrToMember BOOST_INTRUSIVE_MORE , proto_value_traits)
//template< class Parent , class MemberHook , MemberHook Parent::* PtrToMember>
//struct member_hook {
// template<class Base> struct pack : Base {
// typedef mhtraits < Parent , MemberHook , PtrToMember > proto_value_traits;
// };
//};
//
//#undef BOOST_INTRUSIVE_COMMA
//#undef BOOST_INTRUSIVE_LESS
//#undef BOOST_INTRUSIVE_MORE
//!This option setter specifies the member hook the
//!container must use.
@@ -336,27 +264,21 @@ template< typename Parent
, MemberHook Parent::* PtrToMember>
struct member_hook
{
/// @cond
/*
typedef typename MemberHook::hooktags::node_traits node_traits;
typedef typename node_traits::node node_type;
typedef node_type Parent::* Ptr2MemNode;
typedef mhtraits
< Parent
, node_traits
//This cast is really ugly but necessary to reduce template bloat.
//Since we control the layout between the hook and the node, and there is
//always single inheritance, the offset of the node is exactly the offset of
//the hook. Since the node type is shared between all member hooks, this saves
//quite a lot of symbol stuff.
, (Ptr2MemNode)PtrToMember
, MemberHook::hooktags::link_mode> member_value_traits;
*/
typedef mhtraits
< Parent
, MemberHook
, PtrToMember
> member_value_traits;
// @cond
// typedef typename MemberHook::hooktags::node_traits node_traits;
// typedef typename node_traits::node node_type;
// typedef node_type Parent::* Ptr2MemNode;
// typedef mhtraits
// < Parent
// , node_traits
// //This cast is really ugly but necessary to reduce template bloat.
// //Since we control the layout between the hook and the node, and there is
// //always single inheritance, the offset of the node is exactly the offset of
// //the hook. Since the node type is shared between all member hooks, this saves
// //quite a lot of symbol stuff.
// , (Ptr2MemNode)PtrToMember
// , MemberHook::hooktags::link_mode> member_value_traits;
typedef mhtraits <Parent, MemberHook, PtrToMember> member_value_traits;
template<class Base>
struct pack : Base
{
@@ -365,158 +287,54 @@ struct member_hook
/// @endcond
};
//!This option setter specifies the function object that will
//!be used to convert between values to be inserted in a container
//!and the hook to be used for that purpose.
template< typename Functor>
struct function_hook
{
/// @cond
typedef fhtraits
<Functor> function_value_traits;
template<class Base>
struct pack : Base
{
typedef function_value_traits proto_value_traits;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_TYPE(function_hook, Functor, fhtraits<Functor>, proto_value_traits)
//!This option setter specifies that the container
//!must use the specified base hook
template<typename BaseHook>
struct base_hook
{
/// @cond
template<class Base>
struct pack : Base
{
typedef BaseHook proto_value_traits;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_TYPE(base_hook, BaseHook, BaseHook, proto_value_traits)
//!This option setter specifies the type of
//!a void pointer. This will instruct the hook
//!to use this type of pointer instead of the
//!default one
template<class VoidPointer>
struct void_pointer
{
/// @cond
template<class Base>
struct pack : Base
{
typedef VoidPointer void_pointer;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_TYPE(void_pointer, VoidPointer, VoidPointer, void_pointer)
//!This option setter specifies the type of
//!the tag of a base hook. A type cannot have two
//!base hooks of the same type, so a tag can be used
//!to differentiate two base hooks with otherwise same type
template<class Tag>
struct tag
{
/// @cond
template<class Base>
struct pack : Base
{
typedef Tag tag;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_TYPE(tag, Tag, Tag, tag)
//!This option setter specifies the link mode
//!(normal_link, safe_link or auto_unlink)
template<link_mode_type LinkType>
struct link_mode
{
/// @cond
template<class Base>
struct pack : Base
{
static const link_mode_type link_mode = LinkType;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_CONSTANT(link_mode, link_mode_type, LinkType, link_mode)
//!This option setter specifies if the hook
//!should be optimized for size instead of for speed.
template<bool Enabled>
struct optimize_size
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool optimize_size = Enabled;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_CONSTANT(optimize_size, bool, Enabled, optimize_size)
//!This option setter specifies if the list container should
//!use a linear implementation instead of a circular one.
template<bool Enabled>
struct linear
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool linear = Enabled;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_CONSTANT(linear, bool, Enabled, linear)
//!This option setter specifies if the list container should
//!use a linear implementation instead of a circular one.
template<bool Enabled>
struct cache_last
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool cache_last = Enabled;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_CONSTANT(cache_last, bool, Enabled, cache_last)
//!This option setter specifies the bucket traits
//!class for unordered associative containers. When this option is specified,
//!instead of using the default bucket traits, a user defined holder will be defined
template<class BucketTraits>
struct bucket_traits
{
/// @cond
template<class Base>
struct pack : Base
{
typedef BucketTraits bucket_traits;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_TYPE(bucket_traits, BucketTraits, BucketTraits, bucket_traits)
//!This option setter specifies if the unordered hook
//!should offer room to store the hash value.
//!Storing the hash in the hook will speed up rehashing
//!processes in applications where rehashing is frequent,
//!rehashing might throw or the value is heavy to hash.
template<bool Enabled>
struct store_hash
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool store_hash = Enabled;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_CONSTANT(store_hash, bool, Enabled, store_hash)
//!This option setter specifies if the unordered hook
//!should offer room to store another link to another node
@@ -524,51 +342,20 @@ struct store_hash
//!Storing this link will speed up lookups and insertions on
//!unordered_multiset containers with a great number of elements
//!with the same key.
template<bool Enabled>
struct optimize_multikey
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool optimize_multikey = Enabled;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_CONSTANT(optimize_multikey, bool, Enabled, optimize_multikey)
//!This option setter specifies if the bucket array will be always power of two.
//!This allows using masks instead of the default modulo operation to determine
//!the bucket number from the hash value, leading to better performance.
//!In debug mode, if power of two buckets mode is activated, the bucket length
//!will be checked to through assertions to assure the bucket length is power of two.
template<bool Enabled>
struct power_2_buckets
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool power_2_buckets = Enabled;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_CONSTANT(power_2_buckets, bool, Enabled, power_2_buckets)
//!This option setter specifies if the container will cache a pointer to the first
//!non-empty bucket so that begin() is always constant-time.
//!This is specially helpful when we can have containers with a few elements
//!but with big bucket arrays (that is, hashtables with low load factors).
template<bool Enabled>
struct cache_begin
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool cache_begin = Enabled;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_CONSTANT(cache_begin, bool, Enabled, cache_begin)
//!This option setter specifies if the container will compare the hash value
//!before comparing objects. This option can't be specified if store_hash<>
@@ -576,17 +363,7 @@ struct cache_begin
//!This is specially helpful when we have containers with a high load factor.
//!and the comparison function is much more expensive that comparing already
//!stored hash values.
template<bool Enabled>
struct compare_hash
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool compare_hash = Enabled;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_CONSTANT(compare_hash, bool, Enabled, compare_hash)
//!This option setter specifies if the hash container will use incremental
//!hashing. With incremental hashing the cost of hash table expansion is spread
@@ -594,17 +371,7 @@ struct compare_hash
//!Therefore linear hashing is well suited for interactive applications or real-time
//!appplications where the worst-case insertion time of non-incremental hash containers
//!(rehashing the whole bucket array) is not admisible.
template<bool Enabled>
struct incremental
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool incremental = Enabled;
};
/// @endcond
};
BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, incremental)
/// @cond
@@ -615,210 +382,6 @@ struct none
{};
};
//To-do: pass to variadic templates
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class Prev, class Next>
struct do_pack
{
//Use "pack" member template to pack options
typedef typename Next::template pack<Prev> type;
};
template<class Prev>
struct do_pack<Prev, void>
{
//Avoid packing "void" to shorten template names
typedef Prev type;
};
template
< class DefaultOptions
, class O1 = void
, class O2 = void
, class O3 = void
, class O4 = void
, class O5 = void
, class O6 = void
, class O7 = void
, class O8 = void
, class O9 = void
, class O10 = void
, class O11 = void
>
struct pack_options
{
// join options
typedef
typename do_pack
< typename do_pack
< typename do_pack
< typename do_pack
< typename do_pack
< typename do_pack
< typename do_pack
< typename do_pack
< typename do_pack
< typename do_pack
< typename do_pack
< DefaultOptions
, O1
>::type
, O2
>::type
, O3
>::type
, O4
>::type
, O5
>::type
, O6
>::type
, O7
>::type
, O8
>::type
, O9
>::type
, O10
>::type
, O11
>::type
type;
};
#else
//index_tuple
template<int... Indexes>
struct index_tuple{};
//build_number_seq
template<std::size_t Num, typename Tuple = index_tuple<> >
struct build_number_seq;
template<std::size_t Num, int... Indexes>
struct build_number_seq<Num, index_tuple<Indexes...> >
: build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
{};
template<int... Indexes>
struct build_number_seq<0, index_tuple<Indexes...> >
{ typedef index_tuple<Indexes...> type; };
template<class ...Types>
struct typelist
{};
//invert_typelist
template<class T>
struct invert_typelist;
template<int I, typename Tuple>
struct typelist_element;
template<int I, typename Head, typename... Tail>
struct typelist_element<I, typelist<Head, Tail...> >
{
typedef typename typelist_element<I-1, typelist<Tail...> >::type type;
};
template<typename Head, typename... Tail>
struct typelist_element<0, typelist<Head, Tail...> >
{
typedef Head type;
};
template<int ...Ints, class ...Types>
typelist<typename typelist_element<(sizeof...(Types) - 1) - Ints, typelist<Types...> >::type...>
inverted_typelist(index_tuple<Ints...>, typelist<Types...>)
{
return typelist<typename typelist_element<(sizeof...(Types) - 1) - Ints, typelist<Types...> >::type...>();
}
//sizeof_typelist
template<class Typelist>
struct sizeof_typelist;
template<class ...Types>
struct sizeof_typelist< typelist<Types...> >
{
static const std::size_t value = sizeof...(Types);
};
//invert_typelist_impl
template<class Typelist, class Indexes>
struct invert_typelist_impl;
template<class Typelist, int ...Ints>
struct invert_typelist_impl< Typelist, index_tuple<Ints...> >
{
static const std::size_t last_idx = sizeof_typelist<Typelist>::value - 1;
typedef typelist
<typename typelist_element<last_idx - Ints, Typelist>::type...> type;
};
template<class Typelist, int Int>
struct invert_typelist_impl< Typelist, index_tuple<Int> >
{
typedef Typelist type;
};
template<class Typelist>
struct invert_typelist_impl< Typelist, index_tuple<> >
{
typedef Typelist type;
};
//invert_typelist
template<class Typelist>
struct invert_typelist;
template<class ...Types>
struct invert_typelist< typelist<Types...> >
{
typedef typelist<Types...> typelist_t;
typedef typename build_number_seq<sizeof...(Types)>::type indexes_t;
typedef typename invert_typelist_impl<typelist_t, indexes_t>::type type;
};
//Do pack
template<class Typelist>
struct do_pack;
template<>
struct do_pack<typelist<> >;
template<class Prev>
struct do_pack<typelist<Prev> >
{
typedef Prev type;
};
template<class Prev, class Last>
struct do_pack<typelist<Prev, Last> >
{
typedef typename Prev::template pack<Last> type;
};
template<class Prev, class ...Others>
struct do_pack<typelist<Prev, Others...> >
{
typedef typename Prev::template pack
<typename do_pack<typelist<Others...> >::type> type;
};
template<class ...Options>
struct pack_options
{
typedef typelist<Options...> typelist_t;
typedef typename invert_typelist<typelist_t>::type inverted_typelist;
typedef typename do_pack<inverted_typelist>::type type;
};
#endif
struct hook_defaults
{
typedef void* void_pointer;
+370
View File
@@ -0,0 +1,370 @@
/////////////////////////////////////////////////////////////////////////////
//
// (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.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_PACK_OPTIONS_HPP
#define BOOST_INTRUSIVE_PACK_OPTIONS_HPP
#include <boost/intrusive/detail/config_begin.hpp>
namespace boost {
namespace intrusive {
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class Prev, class Next>
struct do_pack
{
//Use "pack" member template to pack options
typedef typename Next::template pack<Prev> type;
};
template<class Prev>
struct do_pack<Prev, void>
{
//Avoid packing "void" to shorten template names
typedef Prev type;
};
template
< class DefaultOptions
, class O1 = void
, class O2 = void
, class O3 = void
, class O4 = void
, class O5 = void
, class O6 = void
, class O7 = void
, class O8 = void
, class O9 = void
, class O10 = void
, class O11 = void
>
struct pack_options
{
// join options
typedef
typename do_pack
< typename do_pack
< typename do_pack
< typename do_pack
< typename do_pack
< typename do_pack
< typename do_pack
< typename do_pack
< typename do_pack
< typename do_pack
< typename do_pack
< DefaultOptions
, O1
>::type
, O2
>::type
, O3
>::type
, O4
>::type
, O5
>::type
, O6
>::type
, O7
>::type
, O8
>::type
, O9
>::type
, O10
>::type
, O11
>::type
type;
};
#else
//index_tuple
template<int... Indexes>
struct index_tuple{};
//build_number_seq
template<std::size_t Num, typename Tuple = index_tuple<> >
struct build_number_seq;
template<std::size_t Num, int... Indexes>
struct build_number_seq<Num, index_tuple<Indexes...> >
: build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
{};
template<int... Indexes>
struct build_number_seq<0, index_tuple<Indexes...> >
{ typedef index_tuple<Indexes...> type; };
template<class ...Types>
struct typelist
{};
//invert_typelist
template<class T>
struct invert_typelist;
template<int I, typename Tuple>
struct typelist_element;
template<int I, typename Head, typename... Tail>
struct typelist_element<I, typelist<Head, Tail...> >
{
typedef typename typelist_element<I-1, typelist<Tail...> >::type type;
};
template<typename Head, typename... Tail>
struct typelist_element<0, typelist<Head, Tail...> >
{
typedef Head type;
};
template<int ...Ints, class ...Types>
typelist<typename typelist_element<(sizeof...(Types) - 1) - Ints, typelist<Types...> >::type...>
inverted_typelist(index_tuple<Ints...>, typelist<Types...>)
{
return typelist<typename typelist_element<(sizeof...(Types) - 1) - Ints, typelist<Types...> >::type...>();
}
//sizeof_typelist
template<class Typelist>
struct sizeof_typelist;
template<class ...Types>
struct sizeof_typelist< typelist<Types...> >
{
static const std::size_t value = sizeof...(Types);
};
//invert_typelist_impl
template<class Typelist, class Indexes>
struct invert_typelist_impl;
template<class Typelist, int ...Ints>
struct invert_typelist_impl< Typelist, index_tuple<Ints...> >
{
static const std::size_t last_idx = sizeof_typelist<Typelist>::value - 1;
typedef typelist
<typename typelist_element<last_idx - Ints, Typelist>::type...> type;
};
template<class Typelist, int Int>
struct invert_typelist_impl< Typelist, index_tuple<Int> >
{
typedef Typelist type;
};
template<class Typelist>
struct invert_typelist_impl< Typelist, index_tuple<> >
{
typedef Typelist type;
};
//invert_typelist
template<class Typelist>
struct invert_typelist;
template<class ...Types>
struct invert_typelist< typelist<Types...> >
{
typedef typelist<Types...> typelist_t;
typedef typename build_number_seq<sizeof...(Types)>::type indexes_t;
typedef typename invert_typelist_impl<typelist_t, indexes_t>::type type;
};
//Do pack
template<class Typelist>
struct do_pack;
template<>
struct do_pack<typelist<> >;
template<class Prev>
struct do_pack<typelist<Prev> >
{
typedef Prev type;
};
template<class Prev, class Last>
struct do_pack<typelist<Prev, Last> >
{
typedef typename Prev::template pack<Last> type;
};
template<class Prev, class ...Others>
struct do_pack<typelist<Prev, Others...> >
{
typedef typename Prev::template pack
<typename do_pack<typelist<Others...> >::type> type;
};
template<class DefaultOptions, class ...Options>
struct pack_options
{
typedef typelist<DefaultOptions, Options...> typelist_t;
typedef typename invert_typelist<typelist_t>::type inverted_typelist;
typedef typename do_pack<inverted_typelist>::type type;
};
#endif //!defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
#define BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) \
template< class TYPE> \
struct OPTION_NAME \
{ \
template<class Base> \
struct pack : Base \
{ \
typedef TYPEDEF_EXPR TYPEDEF_NAME; \
}; \
}; \
//
#define BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) \
template< TYPE VALUE> \
struct OPTION_NAME \
{ \
template<class Base> \
struct pack : Base \
{ \
static const TYPE CONSTANT_NAME = VALUE; \
}; \
}; \
//
#else //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! This class is a utility that takes:
//! - a default options class defining initial static constant
//! and typedefs
//! - several options defined with BOOST_INTRUSIVE_OPTION_CONSTANT and
//! BOOST_INTRUSIVE_OPTION_TYPE
//!
//! and packs them together in a new type that defines all options as
//! member typedefs or static constant values. Given options of form:
//!
//! \code
//! BOOST_INTRUSIVE_OPTION_TYPE(my_pointer, VoidPointer, VoidPointer, my_pointer_type)
//! BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, is_incremental)
//! \endcode
//!
//! the following expression
//!
//! \code
//!
//! struct default_options
//! {
//! typedef long int_type;
//! static const int int_constant = -1;
//! };
//!
//! pack_options< default_options, my_pointer<void*>, incremental<true> >::type
//! \endcode
//!
//! will create a type that will contain the following typedefs/constants
//!
//! \code
//! struct unspecified_type
//! {
//! //Default options
//! typedef long int_type;
//! static const int int_constant = -1;
//!
//! //Packed options (will ovewrite any default option)
//! typedef void* my_pointer_type;
//! static const bool is_incremental = true;
//! };
//! \endcode
//!
//! If an option is specified in the default options argument and later
//! redefined as an option, the last definition will prevail.
template<class DefaultOptions, class ...Options>
struct pack_options
{
typedef unspecified_type type;
};
//! Defines an option class of name OPTION_NAME that can be used to specify a type
//! of type TYPE...
//!
//! \code
//! struct OPTION_NAME<class TYPE>
//! { /*unspecified_content*/ };
//! \endcode
//!
//! ...that after being combined with
//! <code>boost::intrusive::pack_options</code>,
//! will typedef TYPE as a typedef of name TYPEDEF_NAME. Example:
//!
//! \code
//! //[includes and namespaces omitted for brevity]
//!
//! //This macro will create the following class:
//! // template<class VoidPointer>
//! // struct my_pointer
//! // { unspecified_content };
//! BOOST_INTRUSIVE_OPTION_TYPE(my_pointer, VoidPointer, boost::remove_pointer<VoidPointer>::type, my_pointer_type)
//!
//! struct empty_default{};
//!
//! typedef pack_options< empty_default, typename my_pointer<void*> >::type::my_pointer_type type;
//!
//! BOOST_STATIC_ASSERT(( boost::is_same<type, void>::value ));
//!
//! \endcode
#define BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME)
//! Defines an option class of name OPTION_NAME that can be used to specify a constant
//! of type TYPE with value VALUE...
//!
//! \code
//! struct OPTION_NAME<TYPE VALUE>
//! { /*unspecified_content*/ };
//! \endcode
//!
//! ...that after being combined with
//! <code>boost::intrusive::pack_options</code>,
//! will contain a CONSTANT_NAME static constant of value VALUE. Example:
//!
//! \code
//! //[includes and namespaces omitted for brevity]
//!
//! //This macro will create the following class:
//! // template<bool Enabled>
//! // struct incremental
//! // { unspecified_content };
//! BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, is_incremental)
//!
//! struct empty_default{};
//!
//! const bool is_incremental = pack_options< empty_default, incremental<true> >::type::is_incremental;
//!
//! BOOST_STATIC_ASSERT(( is_incremental == true ));
//!
//! \endcode
#define BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME)
#endif //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
} //namespace intrusive {
} //namespace boost {
#include <boost/intrusive/detail/config_end.hpp>
#endif //#ifndef BOOST_INTRUSIVE_PACK_OPTIONS_HPP