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