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
22namespace boost {
23namespace intrusive {
24
25#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
26
27#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
28
29template<class Prev, class Next>
30struct do_pack
31{
32 //Use "pack" member template to pack options
33 typedef typename Next::template pack<Prev> type;
34};
35
36template<class Prev>
37struct do_pack<Prev, void>
38{
39 //Avoid packing "void" to shorten template names
40 typedef Prev type;
41};
42
43template
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 >
57struct 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
100template<int... Indexes>
101struct index_tuple{};
102
103//build_number_seq
104template<std::size_t Num, typename Tuple = index_tuple<> >
105struct build_number_seq;
106
107template<std::size_t Num, int... Indexes>
108struct build_number_seq<Num, index_tuple<Indexes...> >
109 : build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
110{};
111
112template<int... Indexes>
113struct build_number_seq<0, index_tuple<Indexes...> >
114{ typedef index_tuple<Indexes...> type; };
115
116template<class ...Types>
117struct typelist
118{};
119
120//invert_typelist
121template<class T>
122struct invert_typelist;
123
124template<int I, typename Tuple>
125struct typelist_element;
126
127template<int I, typename Head, typename... Tail>
128struct typelist_element<I, typelist<Head, Tail...> >
129{
130 typedef typename typelist_element<I-1, typelist<Tail...> >::type type;
131};
132
133template<typename Head, typename... Tail>
134struct typelist_element<0, typelist<Head, Tail...> >
135{
136 typedef Head type;
137};
138
139template<int ...Ints, class ...Types>
140typelist<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
147template<class Typelist>
148struct sizeof_typelist;
149
150template<class ...Types>
151struct sizeof_typelist< typelist<Types...> >
152{
153 static const std::size_t value = sizeof...(Types);
154};
155
156//invert_typelist_impl
157template<class Typelist, class Indexes>
158struct invert_typelist_impl;
159
160
161template<class Typelist, int ...Ints>
162struct 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
169template<class Typelist, int Int>
170struct invert_typelist_impl< Typelist, index_tuple<Int> >
171{
172 typedef Typelist type;
173};
174
175template<class Typelist>
176struct invert_typelist_impl< Typelist, index_tuple<> >
177{
178 typedef Typelist type;
179};
180
181//invert_typelist
182template<class Typelist>
183struct invert_typelist;
184
185template<class ...Types>
186struct 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
194template<class Typelist>
195struct do_pack;
196
197template<>
198struct do_pack<typelist<> >;
199
200template<class Prev>
201struct do_pack<typelist<Prev> >
202{
203 typedef Prev type;
204};
205
206template<class Prev, class Last>
207struct do_pack<typelist<Prev, Last> >
208{
209 typedef typename Prev::template pack<Last> type;
210};
211
212template<class Prev, class ...Others>
213struct do_pack<typelist<Prev, Others...> >
214{
215 typedef typename Prev::template pack
216 <typename do_pack<typelist<Others...> >::type> type;
217};
218
219
220template<class DefaultOptions, class ...Options>
221struct 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) \
231template< class TYPE> \
232struct 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) \
243template< TYPE VALUE> \
244struct 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.
300template<class DefaultOptions, class ...Options>
301struct 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