Chris@102: ///////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // (C) Copyright Ion Gaztanaga 2013-2013 Chris@102: // Chris@102: // Distributed under the Boost Software License, Version 1.0. Chris@102: // (See accompanying file LICENSE_1_0.txt or copy at Chris@102: // http://www.boost.org/LICENSE_1_0.txt) Chris@102: // Chris@102: // See http://www.boost.org/libs/intrusive for documentation. Chris@102: // Chris@102: ///////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: #ifndef BOOST_INTRUSIVE_PACK_OPTIONS_HPP Chris@102: #define BOOST_INTRUSIVE_PACK_OPTIONS_HPP Chris@102: Chris@102: #include Chris@102: Chris@102: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@102: # pragma once Chris@102: #endif Chris@102: Chris@102: namespace boost { Chris@102: namespace intrusive { Chris@102: Chris@102: #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED Chris@102: Chris@102: #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) Chris@102: Chris@102: template Chris@102: struct do_pack Chris@102: { Chris@102: //Use "pack" member template to pack options Chris@102: typedef typename Next::template pack type; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct do_pack Chris@102: { Chris@102: //Avoid packing "void" to shorten template names Chris@102: typedef Prev type; Chris@102: }; Chris@102: Chris@102: template Chris@102: < class DefaultOptions Chris@102: , class O1 = void Chris@102: , class O2 = void Chris@102: , class O3 = void Chris@102: , class O4 = void Chris@102: , class O5 = void Chris@102: , class O6 = void Chris@102: , class O7 = void Chris@102: , class O8 = void Chris@102: , class O9 = void Chris@102: , class O10 = void Chris@102: , class O11 = void Chris@102: > Chris@102: struct pack_options Chris@102: { Chris@102: // join options Chris@102: typedef Chris@102: typename do_pack Chris@102: < typename do_pack Chris@102: < typename do_pack Chris@102: < typename do_pack Chris@102: < typename do_pack Chris@102: < typename do_pack Chris@102: < typename do_pack Chris@102: < typename do_pack Chris@102: < typename do_pack Chris@102: < typename do_pack Chris@102: < typename do_pack Chris@102: < DefaultOptions Chris@102: , O1 Chris@102: >::type Chris@102: , O2 Chris@102: >::type Chris@102: , O3 Chris@102: >::type Chris@102: , O4 Chris@102: >::type Chris@102: , O5 Chris@102: >::type Chris@102: , O6 Chris@102: >::type Chris@102: , O7 Chris@102: >::type Chris@102: , O8 Chris@102: >::type Chris@102: , O9 Chris@102: >::type Chris@102: , O10 Chris@102: >::type Chris@102: , O11 Chris@102: >::type Chris@102: type; Chris@102: }; Chris@102: #else Chris@102: Chris@102: //index_tuple Chris@102: template Chris@102: struct index_tuple{}; Chris@102: Chris@102: //build_number_seq Chris@102: template > Chris@102: struct build_number_seq; Chris@102: Chris@102: template Chris@102: struct build_number_seq > Chris@102: : build_number_seq > Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct build_number_seq<0, index_tuple > Chris@102: { typedef index_tuple type; }; Chris@102: Chris@102: template Chris@102: struct typelist Chris@102: {}; Chris@102: Chris@102: //invert_typelist Chris@102: template Chris@102: struct invert_typelist; Chris@102: Chris@102: template Chris@102: struct typelist_element; Chris@102: Chris@102: template Chris@102: struct typelist_element > Chris@102: { Chris@102: typedef typename typelist_element >::type type; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct typelist_element<0, typelist > Chris@102: { Chris@102: typedef Head type; Chris@102: }; Chris@102: Chris@102: template Chris@102: typelist >::type...> Chris@102: inverted_typelist(index_tuple, typelist) Chris@102: { Chris@102: return typelist >::type...>(); Chris@102: } Chris@102: Chris@102: //sizeof_typelist Chris@102: template Chris@102: struct sizeof_typelist; Chris@102: Chris@102: template Chris@102: struct sizeof_typelist< typelist > Chris@102: { Chris@102: static const std::size_t value = sizeof...(Types); Chris@102: }; Chris@102: Chris@102: //invert_typelist_impl Chris@102: template Chris@102: struct invert_typelist_impl; Chris@102: Chris@102: Chris@102: template Chris@102: struct invert_typelist_impl< Typelist, index_tuple > Chris@102: { Chris@102: static const std::size_t last_idx = sizeof_typelist::value - 1; Chris@102: typedef typelist Chris@102: ::type...> type; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct invert_typelist_impl< Typelist, index_tuple > Chris@102: { Chris@102: typedef Typelist type; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct invert_typelist_impl< Typelist, index_tuple<> > Chris@102: { Chris@102: typedef Typelist type; Chris@102: }; Chris@102: Chris@102: //invert_typelist Chris@102: template Chris@102: struct invert_typelist; Chris@102: Chris@102: template Chris@102: struct invert_typelist< typelist > Chris@102: { Chris@102: typedef typelist typelist_t; Chris@102: typedef typename build_number_seq::type indexes_t; Chris@102: typedef typename invert_typelist_impl::type type; Chris@102: }; Chris@102: Chris@102: //Do pack Chris@102: template Chris@102: struct do_pack; Chris@102: Chris@102: template<> Chris@102: struct do_pack >; Chris@102: Chris@102: template Chris@102: struct do_pack > Chris@102: { Chris@102: typedef Prev type; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct do_pack > Chris@102: { Chris@102: typedef typename Prev::template pack type; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct do_pack > Chris@102: { Chris@102: typedef typename Prev::template pack Chris@102: >::type> type; Chris@102: }; Chris@102: Chris@102: Chris@102: template Chris@102: struct pack_options Chris@102: { Chris@102: typedef typelist typelist_t; Chris@102: typedef typename invert_typelist::type inverted_typelist; Chris@102: typedef typename do_pack::type type; Chris@102: }; Chris@102: Chris@102: #endif //!defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) Chris@102: Chris@102: #define BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) \ Chris@102: template< class TYPE> \ Chris@102: struct OPTION_NAME \ Chris@102: { \ Chris@102: template \ Chris@102: struct pack : Base \ Chris@102: { \ Chris@102: typedef TYPEDEF_EXPR TYPEDEF_NAME; \ Chris@102: }; \ Chris@102: }; \ Chris@102: // Chris@102: Chris@102: #define BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) \ Chris@102: template< TYPE VALUE> \ Chris@102: struct OPTION_NAME \ Chris@102: { \ Chris@102: template \ Chris@102: struct pack : Base \ Chris@102: { \ Chris@102: static const TYPE CONSTANT_NAME = VALUE; \ Chris@102: }; \ Chris@102: }; \ Chris@102: // Chris@102: Chris@102: #else //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED Chris@102: Chris@102: //! This class is a utility that takes: Chris@102: //! - a default options class defining initial static constant Chris@102: //! and typedefs Chris@102: //! - several options defined with BOOST_INTRUSIVE_OPTION_CONSTANT and Chris@102: //! BOOST_INTRUSIVE_OPTION_TYPE Chris@102: //! Chris@102: //! and packs them together in a new type that defines all options as Chris@102: //! member typedefs or static constant values. Given options of form: Chris@102: //! Chris@102: //! \code Chris@102: //! BOOST_INTRUSIVE_OPTION_TYPE(my_pointer, VoidPointer, VoidPointer, my_pointer_type) Chris@102: //! BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, is_incremental) Chris@102: //! \endcode Chris@102: //! Chris@102: //! the following expression Chris@102: //! Chris@102: //! \code Chris@102: //! Chris@102: //! struct default_options Chris@102: //! { Chris@102: //! typedef long int_type; Chris@102: //! static const int int_constant = -1; Chris@102: //! }; Chris@102: //! Chris@102: //! pack_options< default_options, my_pointer, incremental >::type Chris@102: //! \endcode Chris@102: //! Chris@102: //! will create a type that will contain the following typedefs/constants Chris@102: //! Chris@102: //! \code Chris@102: //! struct unspecified_type Chris@102: //! { Chris@102: //! //Default options Chris@102: //! typedef long int_type; Chris@102: //! static const int int_constant = -1; Chris@102: //! Chris@102: //! //Packed options (will ovewrite any default option) Chris@102: //! typedef void* my_pointer_type; Chris@102: //! static const bool is_incremental = true; Chris@102: //! }; Chris@102: //! \endcode Chris@102: //! Chris@102: //! If an option is specified in the default options argument and later Chris@102: //! redefined as an option, the last definition will prevail. Chris@102: template Chris@102: struct pack_options Chris@102: { Chris@102: typedef unspecified_type type; Chris@102: }; Chris@102: Chris@102: //! Defines an option class of name OPTION_NAME that can be used to specify a type Chris@102: //! of type TYPE... Chris@102: //! Chris@102: //! \code Chris@102: //! struct OPTION_NAME Chris@102: //! { unspecified_content }; Chris@102: //! \endcode Chris@102: //! Chris@102: //! ...that after being combined with Chris@102: //! boost::intrusive::pack_options, Chris@102: //! will typedef TYPE as a typedef of name TYPEDEF_NAME. Example: Chris@102: //! Chris@102: //! \code Chris@102: //! //[includes and namespaces omitted for brevity] Chris@102: //! Chris@102: //! //This macro will create the following class: Chris@102: //! // template Chris@102: //! // struct my_pointer Chris@102: //! // { unspecified_content }; Chris@102: //! BOOST_INTRUSIVE_OPTION_TYPE(my_pointer, VoidPointer, boost::remove_pointer::type, my_pointer_type) Chris@102: //! Chris@102: //! struct empty_default{}; Chris@102: //! Chris@102: //! typedef pack_options< empty_default, typename my_pointer >::type::my_pointer_type type; Chris@102: //! Chris@102: //! BOOST_STATIC_ASSERT(( boost::is_same::value )); Chris@102: //! Chris@102: //! \endcode Chris@102: #define BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) Chris@102: Chris@102: //! Defines an option class of name OPTION_NAME that can be used to specify a constant Chris@102: //! of type TYPE with value VALUE... Chris@102: //! Chris@102: //! \code Chris@102: //! struct OPTION_NAME Chris@102: //! { unspecified_content }; Chris@102: //! \endcode Chris@102: //! Chris@102: //! ...that after being combined with Chris@102: //! boost::intrusive::pack_options, Chris@102: //! will contain a CONSTANT_NAME static constant of value VALUE. Example: Chris@102: //! Chris@102: //! \code Chris@102: //! //[includes and namespaces omitted for brevity] Chris@102: //! Chris@102: //! //This macro will create the following class: Chris@102: //! // template Chris@102: //! // struct incremental Chris@102: //! // { unspecified_content }; Chris@102: //! BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, is_incremental) Chris@102: //! Chris@102: //! struct empty_default{}; Chris@102: //! Chris@102: //! const bool is_incremental = pack_options< empty_default, incremental >::type::is_incremental; Chris@102: //! Chris@102: //! BOOST_STATIC_ASSERT(( is_incremental == true )); Chris@102: //! Chris@102: //! \endcode Chris@102: #define BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) Chris@102: Chris@102: #endif //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED Chris@102: Chris@102: Chris@102: } //namespace intrusive { Chris@102: } //namespace boost { Chris@102: Chris@102: #include Chris@102: Chris@102: #endif //#ifndef BOOST_INTRUSIVE_PACK_OPTIONS_HPP