Move libcds 1.6.0 from SVN
[libcds.git] / cds / opt / make_options_var.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_OPT_MAKE_OPTIONS_VAR_H
4 #define __CDS_OPT_MAKE_OPTIONS_VAR_H
5
6 #ifndef __CDS_OPT_OPTIONS_H
7 #   error <cds/opt/options.h> must be included instead of <cds/opt/make_options_var.h>
8 #endif
9
10 #define CDS_DECL_OPTIONS1   typename... Options
11 #define CDS_DECL_OPTIONS2   typename... Options
12 #define CDS_DECL_OPTIONS3   typename... Options
13 #define CDS_DECL_OPTIONS4   typename... Options
14 #define CDS_DECL_OPTIONS5   typename... Options
15 #define CDS_DECL_OPTIONS6   typename... Options
16 #define CDS_DECL_OPTIONS7   typename... Options
17 #define CDS_DECL_OPTIONS8   typename... Options
18 #define CDS_DECL_OPTIONS9   typename... Options
19 #define CDS_DECL_OPTIONS10  typename... Options
20 #define CDS_DECL_OPTIONS11  typename... Options
21 #define CDS_DECL_OPTIONS12  typename... Options
22 #define CDS_DECL_OPTIONS13  typename... Options
23 #define CDS_DECL_OPTIONS14  typename... Options
24 #define CDS_DECL_OPTIONS15  typename... Options
25 #define CDS_DECL_OPTIONS16  typename... Options
26
27 #define CDS_DECL_OPTIONS    typename... Options
28
29
30 #define CDS_DECL_OTHER_OPTIONS1   typename... Options2
31 #define CDS_DECL_OTHER_OPTIONS2   typename... Options2
32 #define CDS_DECL_OTHER_OPTIONS3   typename... Options2
33 #define CDS_DECL_OTHER_OPTIONS4   typename... Options2
34 #define CDS_DECL_OTHER_OPTIONS5   typename... Options2
35 #define CDS_DECL_OTHER_OPTIONS6   typename... Options2
36 #define CDS_DECL_OTHER_OPTIONS7   typename... Options2
37 #define CDS_DECL_OTHER_OPTIONS8   typename... Options2
38 #define CDS_DECL_OTHER_OPTIONS9   typename... Options2
39 #define CDS_DECL_OTHER_OPTIONS10  typename... Options2
40 #define CDS_DECL_OTHER_OPTIONS11  typename... Options2
41 #define CDS_DECL_OTHER_OPTIONS12  typename... Options2
42 #define CDS_DECL_OTHER_OPTIONS13  typename... Options2
43 #define CDS_DECL_OTHER_OPTIONS14  typename... Options2
44 #define CDS_DECL_OTHER_OPTIONS15  typename... Options2
45 #define CDS_DECL_OTHER_OPTIONS16  typename... Options2
46
47 // for template specializations
48 #define CDS_SPEC_OPTIONS1   typename... Options
49 #define CDS_SPEC_OPTIONS2   typename... Options
50 #define CDS_SPEC_OPTIONS3   typename... Options
51 #define CDS_SPEC_OPTIONS4   typename... Options
52 #define CDS_SPEC_OPTIONS5   typename... Options
53 #define CDS_SPEC_OPTIONS6   typename... Options
54 #define CDS_SPEC_OPTIONS7   typename... Options
55 #define CDS_SPEC_OPTIONS8   typename... Options
56 #define CDS_SPEC_OPTIONS9   typename... Options
57 #define CDS_SPEC_OPTIONS10  typename... Options
58 #define CDS_SPEC_OPTIONS11  typename... Options
59 #define CDS_SPEC_OPTIONS12  typename... Options
60 #define CDS_SPEC_OPTIONS13  typename... Options
61 #define CDS_SPEC_OPTIONS14  typename... Options
62 #define CDS_SPEC_OPTIONS15  typename... Options
63 #define CDS_SPEC_OPTIONS16  typename... Options
64
65 #define CDS_SPEC_OPTIONS    typename... Options
66
67 #define CDS_OPTIONS1    Options...
68 #define CDS_OPTIONS2    Options...
69 #define CDS_OPTIONS3    Options...
70 #define CDS_OPTIONS4    Options...
71 #define CDS_OPTIONS5    Options...
72 #define CDS_OPTIONS6    Options...
73 #define CDS_OPTIONS7    Options...
74 #define CDS_OPTIONS8    Options...
75 #define CDS_OPTIONS9    Options...
76 #define CDS_OPTIONS10   Options...
77 #define CDS_OPTIONS11   Options...
78 #define CDS_OPTIONS12   Options...
79 #define CDS_OPTIONS13   Options...
80 #define CDS_OPTIONS14   Options...
81 #define CDS_OPTIONS15   Options...
82 #define CDS_OPTIONS16   Options...
83 //#define CDS_OPTIONS17   Options...
84 //#define CDS_OPTIONS18   Options...
85 //#define CDS_OPTIONS19   Options...
86 //#define CDS_OPTIONS20   Options...
87
88 #define CDS_OPTIONS     Options...
89
90 #define CDS_OTHER_OPTIONS1    Options2...
91 #define CDS_OTHER_OPTIONS2    Options2...
92 #define CDS_OTHER_OPTIONS3    Options2...
93 #define CDS_OTHER_OPTIONS4    Options2...
94 #define CDS_OTHER_OPTIONS5    Options2...
95 #define CDS_OTHER_OPTIONS6    Options2...
96 #define CDS_OTHER_OPTIONS7    Options2...
97 #define CDS_OTHER_OPTIONS8    Options2...
98 #define CDS_OTHER_OPTIONS9    Options2...
99 #define CDS_OTHER_OPTIONS10   Options2...
100 #define CDS_OTHER_OPTIONS11   Options2...
101 #define CDS_OTHER_OPTIONS12   Options2...
102 #define CDS_OTHER_OPTIONS13   Options2...
103 #define CDS_OTHER_OPTIONS14   Options2...
104 #define CDS_OTHER_OPTIONS15   Options2...
105 #define CDS_OTHER_OPTIONS16   Options2...
106
107 namespace cds { namespace opt {
108
109     //@cond
110     namespace details {
111         template <typename OptionList, typename Option>
112         struct do_pack
113         {
114             // Use "pack" member template to pack options
115             typedef typename Option::template pack<OptionList> type;
116         };
117
118         template <typename ...T> class typelist;
119
120         template <typename Typelist> struct typelist_head;
121         template <typename Head, typename ...Tail>
122         struct typelist_head< typelist<Head, Tail...> > {
123             typedef Head type;
124         };
125         template <typename Head>
126         struct typelist_head< typelist<Head> > {
127             typedef Head type;
128         };
129
130         template <typename Typelist> struct typelist_tail;
131         template <typename Head, typename ...Tail>
132         struct typelist_tail< typelist<Head, Tail...> > {
133             typedef typelist<Tail...> type;
134         };
135         template <typename Head>
136         struct typelist_tail< typelist<Head> > {
137             typedef typelist<> type;
138         };
139
140         template <typename OptionList, typename Typelist>
141         struct make_options_impl {
142             typedef typename make_options_impl<
143                 typename do_pack<
144                     OptionList,
145                     typename typelist_head< Typelist >::type
146                 >::type,
147                 typename typelist_tail<Typelist>::type
148             >::type type;
149         };
150
151         template <typename OptionList>
152         struct make_options_impl<OptionList, typelist<> > {
153             typedef OptionList type;
154         };
155     }   // namespace details
156     //@endcond
157
158     /// make_options metafunction
159     /** @headerfile cds/opt/options.h
160
161         The metafunction converts option list \p Options to traits structure.
162         The result of metafunction is \p type.
163
164         Template parameter \p OptionList is default option set (default traits).
165         \p Options is option list.
166     */
167     template <typename OptionList, typename... Options>
168     struct make_options {
169 #ifdef CDS_DOXYGEN_INVOKED
170         typedef implementation_defined type ;   ///< Result of the metafunction
171 #else
172         typedef typename details::make_options_impl< OptionList, details::typelist<Options...> >::type type;
173 #endif
174     };
175
176
177     // *****************************************************************
178     // find_type_traits metafunction
179     // *****************************************************************
180
181     //@cond
182     namespace details {
183         template <typename... Options>
184         struct find_type_traits_option;
185
186         template <>
187         struct find_type_traits_option<> {
188             typedef cds::opt::none  type;
189         };
190
191         template <typename Any>
192         struct find_type_traits_option< Any > {
193             typedef cds::opt::none type;
194         };
195
196         template <typename Any>
197         struct find_type_traits_option< cds::opt::type_traits< Any > > {
198             typedef Any type;
199         };
200
201         template <typename Any, typename... Options>
202         struct find_type_traits_option< cds::opt::type_traits< Any >, Options... > {
203             typedef Any type;
204         };
205
206         template <typename Any, typename... Options>
207         struct find_type_traits_option< Any, Options... > {
208             typedef typename find_type_traits_option< Options... >::type type;
209         };
210     } // namespace details
211     //@endcond
212
213     /// Metafunction to find opt::type_traits option in \p Options list
214     /** @headerfile cds/opt/options.h
215
216         If \p Options contains opt::type_traits option then it is the metafunction result.
217         Otherwise the result is \p DefaultOptons.
218     */
219     template <typename DefaultOptions, typename... Options>
220     struct find_type_traits {
221         typedef typename select_default< typename details::find_type_traits_option<Options...>::type, DefaultOptions>::type type ;  ///< Metafunction result
222     };
223
224
225     // *****************************************************************
226     // find_option metafunction
227     // *****************************************************************
228
229     //@cond
230     namespace details {
231         template <typename What, typename... Options>
232         struct find_option;
233
234         struct compare_ok;
235         struct compare_fail;
236
237         template <typename A, typename B>
238         struct compare_option
239         {
240             typedef compare_fail type;
241         };
242
243         template <template <typename> class Opt, typename A, typename B>
244         struct compare_option< Opt<A>, Opt<B> >
245         {
246             typedef compare_ok   type;
247         };
248
249         // Specializations for integral type of option
250 #define _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION( _type ) template <template <_type> class What, _type A, _type B> \
251         struct compare_option< What<A>, What<B> > { typedef compare_ok type ; };
252
253         // For user-defined enum types
254 #define CDS_DECLARE_FIND_OPTION_INTEGRAL_SPECIALIZATION( _type ) namespace cds { namespace opt { namespace details { _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(_type ) }}}
255
256         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(bool)
257         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(char)
258         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(unsigned char)
259         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(signed char)
260         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(short int)
261         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(unsigned short int)
262         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(int)
263         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(unsigned int)
264         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(long)
265         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(unsigned long)
266         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(long long)
267         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(unsigned long long)
268
269
270         template <typename CompResult, typename Ok, typename Fail>
271         struct select_option
272         {
273             typedef Fail    type;
274         };
275
276         template <typename Ok, typename Fail>
277         struct select_option< compare_ok, Ok, Fail >
278         {
279             typedef Ok      type;
280         };
281
282         template <typename What>
283         struct find_option< What > {
284             typedef What    type;
285         };
286
287         template <typename What, typename Opt>
288         struct find_option< What, Opt > {
289             typedef typename select_option<
290                 typename compare_option< What, Opt >::type
291                 ,Opt
292                 ,What
293             >::type type;
294         };
295
296         template <typename What, typename Opt, typename... Options>
297         struct find_option< What, Opt, Options... > {
298             typedef typename select_option<
299                 typename compare_option< What, Opt >::type
300                 ,Opt
301                 ,typename find_option< What, Options... >::type
302             >::type type;
303         };
304     } // namespace details
305     //@endcond
306
307     /// Metafunction to find \p What option in \p Options list
308     /** @headerfile cds/opt/options.h
309
310         If \p Options contains \p What< Val > option for any \p Val then the result is \p What< Val >
311         Otherwise the result is \p What.
312
313         Example:
314         \code
315         #include <cds/opt/options.h>
316         namespace co = cds::opt;
317
318         struct default_tag;
319         struct tag_a;
320         struct tag_b;
321
322         // Find option co::tag.
323
324         // res1 is co::tag< tag_a >
325         typedef co::find_option< co::tag< default_tag >, co::gc< cds::gc::HP >, co::tag< tag_a > >::type res1;
326
327         // res2 is default co::tag< default_tag >
328         typedef co::find_option< co::tag< default_tag >, co::less< x >, co::hash< H > >::type res2;
329
330         // Multiple option co::tag. The first option is selected
331         // res3 is default co::tag< tag_a >
332         typedef co::find_option< co::tag< default_tag >, co::tag< tag_a >, co::tag< tag_b > >::type res3;
333
334         \endcode
335     */
336     template <typename What, typename... Options>
337     struct find_option {
338         typedef typename details::find_option<What, Options...>::type   type ;  ///< Metafunction result
339     };
340
341
342     // *****************************************************************
343     // select metafunction
344     // *****************************************************************
345
346     //@cond
347     namespace details {
348
349         template <typename What, typename... Pairs>
350         struct select;
351
352         template <typename What, typename Value>
353         struct select< What, What, Value>
354         {
355             typedef Value   type;
356         };
357
358         template <typename What, typename Tag, typename Value>
359         struct select<What, Tag, Value>
360         {
361             typedef What    type;
362         };
363
364         template <typename What, typename Value, typename... Pairs>
365         struct select< What, What, Value, Pairs...>
366         {
367             typedef Value   type;
368         };
369
370         template <typename What, typename Tag, typename Value, typename... Pairs>
371         struct select< What, Tag, Value, Pairs...>
372         {
373             typedef typename select<What, Pairs...>::type   type;
374         };
375     }   // namespace details
376     //@endcond
377
378     /// Select option metafunction
379     /** @headerfile cds/opt/options.h
380
381         Pseudocode:
382         \code
383         select <What, T1, R1, T2, R2, ... Tn, Rn> ::=
384             if What == T1 then return R1
385             if What == T2 then return R2
386             ...
387             if What == Tn then return Rn
388             else return What
389         \endcode
390     */
391     template <typename What, typename... Pairs>
392     struct select {
393         typedef typename details::select< What, Pairs...>::type  type    ;   ///< Metafunction result
394     };
395
396 }}  // namespace cds::opt
397
398 #endif // #ifndef __CDS_OPT_MAKE_OPTIONS_STD_H