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 | |