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