pack_options.hpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2013-2013
  4. //
  5. // Distributed under the Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // See http://www.boost.org/libs/intrusive for documentation.
  10. //
  11. /////////////////////////////////////////////////////////////////////////////
  12. #ifndef BOOST_INTRUSIVE_PACK_OPTIONS_HPP
  13. #define BOOST_INTRUSIVE_PACK_OPTIONS_HPP
  14. #include <boost/intrusive/detail/config_begin.hpp>
  15. #if defined(BOOST_HAS_PRAGMA_ONCE)
  16. # pragma once
  17. #endif
  18. namespace boost {
  19. namespace intrusive {
  20. #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  21. #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
  22. template<class Prev, class Next>
  23. struct do_pack
  24. {
  25. //Use "pack" member template to pack options
  26. typedef typename Next::template pack<Prev> type;
  27. };
  28. template<class Prev>
  29. struct do_pack<Prev, void>
  30. {
  31. //Avoid packing "void" to shorten template names
  32. typedef Prev type;
  33. };
  34. template
  35. < class DefaultOptions
  36. , class O1 = void
  37. , class O2 = void
  38. , class O3 = void
  39. , class O4 = void
  40. , class O5 = void
  41. , class O6 = void
  42. , class O7 = void
  43. , class O8 = void
  44. , class O9 = void
  45. , class O10 = void
  46. , class O11 = void
  47. >
  48. struct pack_options
  49. {
  50. // join options
  51. typedef
  52. typename do_pack
  53. < typename do_pack
  54. < typename do_pack
  55. < typename do_pack
  56. < typename do_pack
  57. < typename do_pack
  58. < typename do_pack
  59. < typename do_pack
  60. < typename do_pack
  61. < typename do_pack
  62. < typename do_pack
  63. < DefaultOptions
  64. , O1
  65. >::type
  66. , O2
  67. >::type
  68. , O3
  69. >::type
  70. , O4
  71. >::type
  72. , O5
  73. >::type
  74. , O6
  75. >::type
  76. , O7
  77. >::type
  78. , O8
  79. >::type
  80. , O9
  81. >::type
  82. , O10
  83. >::type
  84. , O11
  85. >::type
  86. type;
  87. };
  88. #else
  89. //index_tuple
  90. template<int... Indexes>
  91. struct index_tuple{};
  92. //build_number_seq
  93. template<std::size_t Num, typename Tuple = index_tuple<> >
  94. struct build_number_seq;
  95. template<std::size_t Num, int... Indexes>
  96. struct build_number_seq<Num, index_tuple<Indexes...> >
  97. : build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
  98. {};
  99. template<int... Indexes>
  100. struct build_number_seq<0, index_tuple<Indexes...> >
  101. { typedef index_tuple<Indexes...> type; };
  102. template<class ...Types>
  103. struct typelist
  104. {};
  105. //invert_typelist
  106. template<class T>
  107. struct invert_typelist;
  108. template<int I, typename Tuple>
  109. struct typelist_element;
  110. template<int I, typename Head, typename... Tail>
  111. struct typelist_element<I, typelist<Head, Tail...> >
  112. {
  113. typedef typename typelist_element<I-1, typelist<Tail...> >::type type;
  114. };
  115. template<typename Head, typename... Tail>
  116. struct typelist_element<0, typelist<Head, Tail...> >
  117. {
  118. typedef Head type;
  119. };
  120. template<int ...Ints, class ...Types>
  121. typelist<typename typelist_element<(sizeof...(Types) - 1) - Ints, typelist<Types...> >::type...>
  122. inverted_typelist(index_tuple<Ints...>, typelist<Types...>)
  123. {
  124. return typelist<typename typelist_element<(sizeof...(Types) - 1) - Ints, typelist<Types...> >::type...>();
  125. }
  126. //sizeof_typelist
  127. template<class Typelist>
  128. struct sizeof_typelist;
  129. template<class ...Types>
  130. struct sizeof_typelist< typelist<Types...> >
  131. {
  132. static const std::size_t value = sizeof...(Types);
  133. };
  134. //invert_typelist_impl
  135. template<class Typelist, class Indexes>
  136. struct invert_typelist_impl;
  137. template<class Typelist, int ...Ints>
  138. struct invert_typelist_impl< Typelist, index_tuple<Ints...> >
  139. {
  140. static const std::size_t last_idx = sizeof_typelist<Typelist>::value - 1;
  141. typedef typelist
  142. <typename typelist_element<last_idx - Ints, Typelist>::type...> type;
  143. };
  144. template<class Typelist, int Int>
  145. struct invert_typelist_impl< Typelist, index_tuple<Int> >
  146. {
  147. typedef Typelist type;
  148. };
  149. template<class Typelist>
  150. struct invert_typelist_impl< Typelist, index_tuple<> >
  151. {
  152. typedef Typelist type;
  153. };
  154. //invert_typelist
  155. template<class Typelist>
  156. struct invert_typelist;
  157. template<class ...Types>
  158. struct invert_typelist< typelist<Types...> >
  159. {
  160. typedef typelist<Types...> typelist_t;
  161. typedef typename build_number_seq<sizeof...(Types)>::type indexes_t;
  162. typedef typename invert_typelist_impl<typelist_t, indexes_t>::type type;
  163. };
  164. //Do pack
  165. template<class Typelist>
  166. struct do_pack;
  167. template<>
  168. struct do_pack<typelist<> >;
  169. template<class Prev>
  170. struct do_pack<typelist<Prev> >
  171. {
  172. typedef Prev type;
  173. };
  174. template<class Prev, class Last>
  175. struct do_pack<typelist<Prev, Last> >
  176. {
  177. typedef typename Prev::template pack<Last> type;
  178. };
  179. template<class ...Others>
  180. struct do_pack<typelist<void, Others...> >
  181. {
  182. typedef typename do_pack<typelist<Others...> >::type type;
  183. };
  184. template<class Prev, class ...Others>
  185. struct do_pack<typelist<Prev, Others...> >
  186. {
  187. typedef typename Prev::template pack
  188. <typename do_pack<typelist<Others...> >::type> type;
  189. };
  190. template<class DefaultOptions, class ...Options>
  191. struct pack_options
  192. {
  193. typedef typelist<DefaultOptions, Options...> typelist_t;
  194. typedef typename invert_typelist<typelist_t>::type inverted_typelist;
  195. typedef typename do_pack<inverted_typelist>::type type;
  196. };
  197. #endif //!defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
  198. #define BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) \
  199. template< class TYPE> \
  200. struct OPTION_NAME \
  201. { \
  202. template<class Base> \
  203. struct pack : Base \
  204. { \
  205. typedef TYPEDEF_EXPR TYPEDEF_NAME; \
  206. }; \
  207. }; \
  208. //
  209. #define BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) \
  210. template< TYPE VALUE> \
  211. struct OPTION_NAME \
  212. { \
  213. template<class Base> \
  214. struct pack : Base \
  215. { \
  216. static const TYPE CONSTANT_NAME = VALUE; \
  217. }; \
  218. }; \
  219. //
  220. #else //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  221. //! This class is a utility that takes:
  222. //! - a default options class defining initial static constant
  223. //! and typedefs
  224. //! - several options defined with BOOST_INTRUSIVE_OPTION_CONSTANT and
  225. //! BOOST_INTRUSIVE_OPTION_TYPE
  226. //!
  227. //! and packs them together in a new type that defines all options as
  228. //! member typedefs or static constant values. Given options of form:
  229. //!
  230. //! \code
  231. //! BOOST_INTRUSIVE_OPTION_TYPE(my_pointer, VoidPointer, VoidPointer, my_pointer_type)
  232. //! BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, is_incremental)
  233. //! \endcode
  234. //!
  235. //! the following expression
  236. //!
  237. //! \code
  238. //!
  239. //! struct default_options
  240. //! {
  241. //! typedef long int_type;
  242. //! static const int int_constant = -1;
  243. //! };
  244. //!
  245. //! pack_options< default_options, my_pointer<void*>, incremental<true> >::type
  246. //! \endcode
  247. //!
  248. //! will create a type that will contain the following typedefs/constants
  249. //!
  250. //! \code
  251. //! struct unspecified_type
  252. //! {
  253. //! //Default options
  254. //! typedef long int_type;
  255. //! static const int int_constant = -1;
  256. //!
  257. //! //Packed options (will ovewrite any default option)
  258. //! typedef void* my_pointer_type;
  259. //! static const bool is_incremental = true;
  260. //! };
  261. //! \endcode
  262. //!
  263. //! If an option is specified in the default options argument and later
  264. //! redefined as an option, the last definition will prevail.
  265. template<class DefaultOptions, class ...Options>
  266. struct pack_options
  267. {
  268. typedef unspecified_type type;
  269. };
  270. //! Defines an option class of name OPTION_NAME that can be used to specify a type
  271. //! of type TYPE...
  272. //!
  273. //! \code
  274. //! struct OPTION_NAME<class TYPE>
  275. //! { unspecified_content };
  276. //! \endcode
  277. //!
  278. //! ...that after being combined with
  279. //! <code>boost::intrusive::pack_options</code>,
  280. //! will typedef TYPE as a typedef of name TYPEDEF_NAME. Example:
  281. //!
  282. //! \code
  283. //! //[includes and namespaces omitted for brevity]
  284. //!
  285. //! //This macro will create the following class:
  286. //! // template<class VoidPointer>
  287. //! // struct my_pointer
  288. //! // { unspecified_content };
  289. //! BOOST_INTRUSIVE_OPTION_TYPE(my_pointer, VoidPointer, boost::remove_pointer<VoidPointer>::type, my_pointer_type)
  290. //!
  291. //! struct empty_default{};
  292. //!
  293. //! typedef pack_options< empty_default, typename my_pointer<void*> >::type::my_pointer_type type;
  294. //!
  295. //! BOOST_STATIC_ASSERT(( boost::is_same<type, void>::value ));
  296. //!
  297. //! \endcode
  298. #define BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME)
  299. //! Defines an option class of name OPTION_NAME that can be used to specify a constant
  300. //! of type TYPE with value VALUE...
  301. //!
  302. //! \code
  303. //! struct OPTION_NAME<TYPE VALUE>
  304. //! { unspecified_content };
  305. //! \endcode
  306. //!
  307. //! ...that after being combined with
  308. //! <code>boost::intrusive::pack_options</code>,
  309. //! will contain a CONSTANT_NAME static constant of value VALUE. Example:
  310. //!
  311. //! \code
  312. //! //[includes and namespaces omitted for brevity]
  313. //!
  314. //! //This macro will create the following class:
  315. //! // template<bool Enabled>
  316. //! // struct incremental
  317. //! // { unspecified_content };
  318. //! BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, is_incremental)
  319. //!
  320. //! struct empty_default{};
  321. //!
  322. //! const bool is_incremental = pack_options< empty_default, incremental<true> >::type::is_incremental;
  323. //!
  324. //! BOOST_STATIC_ASSERT(( is_incremental == true ));
  325. //!
  326. //! \endcode
  327. #define BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME)
  328. #endif //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  329. } //namespace intrusive {
  330. } //namespace boost {
  331. #include <boost/intrusive/detail/config_end.hpp>
  332. #endif //#ifndef BOOST_INTRUSIVE_PACK_OPTIONS_HPP