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

View File

@@ -53,7 +53,9 @@ doxygen autodoc
\"avltree_impl=avltree\" \\
\"treap_set_impl=treap_set\" \\
\"treap_multiset_impl=treap_multiset\" \\
\"treap_impl=treap\""
\"treap_impl=treap\" \\
\"BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) = template<TYPE VALUE> struct OPTION_NAME{};\" \\
\"BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) = template<class TYPE> struct OPTION_NAME{};\" "
;
xml intrusive : intrusive.qbk

View File

@@ -24,7 +24,8 @@ class MyClass : public auto_unlink_hook
public:
MyClass(int i = 0) : int_(i) {}
void unlink() { auto_unlink_hook::unlink(); }
int get_int() { return int_; }
void unlink() { auto_unlink_hook::unlink(); }
bool is_linked() { return auto_unlink_hook::is_linked(); }
};

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;

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

View File

@@ -115,6 +115,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scary_iterators", "scary_it
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pack_options", "pack_options\pack_options.vcproj", "{77F4139B-281B-F694-7CB1-3495467B4D35}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
@@ -239,6 +243,10 @@ Global
{7679B41B-C1C5-FA34-9614-3547B3140346}.Debug.Build.0 = Debug|Win32
{7679B41B-C1C5-FA34-9614-3547B3140346}.Release.ActiveCfg = Release|Win32
{7679B41B-C1C5-FA34-9614-3547B3140346}.Release.Build.0 = Release|Win32
{77F4139B-281B-F694-7CB1-3495467B4D35}.Debug.ActiveCfg = Debug|Win32
{77F4139B-281B-F694-7CB1-3495467B4D35}.Debug.Build.0 = Debug|Win32
{77F4139B-281B-F694-7CB1-3495467B4D35}.Release.ActiveCfg = Release|Win32
{77F4139B-281B-F694-7CB1-3495467B4D35}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection

View File

@@ -157,6 +157,9 @@
<File
RelativePath="..\..\..\..\..\boost\intrusive\options.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\pack_options.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\parent_from_member.hpp">
</File>

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="pack_options"
ProjectGUID="{77F4139B-281B-F694-7CB1-3495467B4D35}"
RootNamespace="pack_options"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../../../"
PreprocessorDefinitions="BOOST_DATE_TIME_NO_LIB"
GeneratePreprocessedFile="0"
KeepComments="FALSE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
DisableLanguageExtensions="FALSE"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/pack_options.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/pack_options.pdb"
GenerateMapFile="TRUE"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../../../"
PreprocessorDefinitions="BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="4"
DisableLanguageExtensions="FALSE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/pack_options.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{47FFA531-6474-B5A5-A661-272FA537F35F}">
<File
RelativePath="..\..\..\test\pack_options_test.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -21,6 +21,7 @@
Optimization="0"
AdditionalIncludeDirectories="../../../../../"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
GeneratePreprocessedFile="0"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"

View File

@@ -0,0 +1,60 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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/detail/config_begin.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/static_assert.hpp>
#include <boost/intrusive/pack_options.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::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::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::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::is_same<combined_type::my_pointer_type, float >::value ));
BOOST_STATIC_ASSERT(( boost::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::is_same<pack_options<default_options>::type, default_options>::value ));
int main()
{
return 0;
}
#include <boost/intrusive/detail/config_end.hpp>