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 ...Others> 213 struct do_pack<typelist<void, Others...> > 214 { 215 typedef typename do_pack<typelist<Others...> >::type type; 216 }; 217 218 template<class Prev, class ...Others> 219 struct do_pack<typelist<Prev, Others...> > 220 { 221 typedef typename Prev::template pack 222 <typename do_pack<typelist<Others...> >::type> type; 223 }; 224 225 226 template<class DefaultOptions, class ...Options> 227 struct pack_options 228 { 229 typedef typelist<DefaultOptions, Options...> typelist_t; 230 typedef typename invert_typelist<typelist_t>::type inverted_typelist; 231 typedef typename do_pack<inverted_typelist>::type type; 232 }; 233 234 #endif //!defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) 235 236 #define BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) \ 237 template< class TYPE> \ 238 struct OPTION_NAME \ 239 { \ 240 template<class Base> \ 241 struct pack : Base \ 242 { \ 243 typedef TYPEDEF_EXPR TYPEDEF_NAME; \ 244 }; \ 245 }; \ 246 // 247 248 #define BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) \ 249 template< TYPE VALUE> \ 250 struct OPTION_NAME \ 251 { \ 252 template<class Base> \ 253 struct pack : Base \ 254 { \ 255 static const TYPE CONSTANT_NAME = VALUE; \ 256 }; \ 257 }; \ 258 // 259 260 #else //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED 261 262 //! This class is a utility that takes: 263 //! - a default options class defining initial static constant 264 //! and typedefs 265 //! - several options defined with BOOST_INTRUSIVE_OPTION_CONSTANT and 266 //! BOOST_INTRUSIVE_OPTION_TYPE 267 //! 268 //! and packs them together in a new type that defines all options as 269 //! member typedefs or static constant values. Given options of form: 270 //! 271 //! \code 272 //! BOOST_INTRUSIVE_OPTION_TYPE(my_pointer, VoidPointer, VoidPointer, my_pointer_type) 273 //! BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, is_incremental) 274 //! \endcode 275 //! 276 //! the following expression 277 //! 278 //! \code 279 //! 280 //! struct default_options 281 //! { 282 //! typedef long int_type; 283 //! static const int int_constant = -1; 284 //! }; 285 //! 286 //! pack_options< default_options, my_pointer<void*>, incremental<true> >::type 287 //! \endcode 288 //! 289 //! will create a type that will contain the following typedefs/constants 290 //! 291 //! \code 292 //! struct unspecified_type 293 //! { 294 //! //Default options 295 //! typedef long int_type; 296 //! static const int int_constant = -1; 297 //! 298 //! //Packed options (will ovewrite any default option) 299 //! typedef void* my_pointer_type; 300 //! static const bool is_incremental = true; 301 //! }; 302 //! \endcode 303 //! 304 //! If an option is specified in the default options argument and later 305 //! redefined as an option, the last definition will prevail. 306 template<class DefaultOptions, class ...Options> 307 struct pack_options 308 { 309 typedef unspecified_type type; 310 }; 311 312 //! Defines an option class of name OPTION_NAME that can be used to specify a type 313 //! of type TYPE... 314 //! 315 //! \code 316 //! struct OPTION_NAME<class TYPE> 317 //! { unspecified_content }; 318 //! \endcode 319 //! 320 //! ...that after being combined with 321 //! <code>boost::intrusive::pack_options</code>, 322 //! will typedef TYPE as a typedef of name TYPEDEF_NAME. Example: 323 //! 324 //! \code 325 //! //[includes and namespaces omitted for brevity] 326 //! 327 //! //This macro will create the following class: 328 //! // template<class VoidPointer> 329 //! // struct my_pointer 330 //! // { unspecified_content }; 331 //! BOOST_INTRUSIVE_OPTION_TYPE(my_pointer, VoidPointer, boost::remove_pointer<VoidPointer>::type, my_pointer_type) 332 //! 333 //! struct empty_default{}; 334 //! 335 //! typedef pack_options< empty_default, typename my_pointer<void*> >::type::my_pointer_type type; 336 //! 337 //! BOOST_STATIC_ASSERT(( boost::is_same<type, void>::value )); 338 //! 339 //! \endcode 340 #define BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) 341 342 //! Defines an option class of name OPTION_NAME that can be used to specify a constant 343 //! of type TYPE with value VALUE... 344 //! 345 //! \code 346 //! struct OPTION_NAME<TYPE VALUE> 347 //! { unspecified_content }; 348 //! \endcode 349 //! 350 //! ...that after being combined with 351 //! <code>boost::intrusive::pack_options</code>, 352 //! will contain a CONSTANT_NAME static constant of value VALUE. Example: 353 //! 354 //! \code 355 //! //[includes and namespaces omitted for brevity] 356 //! 357 //! //This macro will create the following class: 358 //! // template<bool Enabled> 359 //! // struct incremental 360 //! // { unspecified_content }; 361 //! BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, is_incremental) 362 //! 363 //! struct empty_default{}; 364 //! 365 //! const bool is_incremental = pack_options< empty_default, incremental<true> >::type::is_incremental; 366 //! 367 //! BOOST_STATIC_ASSERT(( is_incremental == true )); 368 //! 369 //! \endcode 370 #define BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) 371 372 #endif //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED 373 374 375 } //namespace intrusive { 376 } //namespace boost { 377 378 #include <boost/intrusive/detail/config_end.hpp> 379 380 #endif //#ifndef BOOST_INTRUSIVE_PACK_OPTIONS_HPP 381