pack_options.hpp 10 KB

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