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