375 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			375 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | ///////////////////////////////////////////////////////////////////////////// | ||
|  | // | ||
|  | // (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> | ||
|  | 
 | ||
|  | #if defined(BOOST_HAS_PRAGMA_ONCE) | ||
|  | #  pragma once | ||
|  | #endif | ||
|  | 
 | ||
|  | 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 |