issue#11: cds: changed __CDS_ guard prefix to CDSLIB_ for all .h files
[libcds.git] / cds / opt / make_options_var.h
1 //$$CDS-header$$
2
3 #ifndef CDSLIB_OPT_MAKE_OPTIONS_VAR_H
4 #define CDSLIB_OPT_MAKE_OPTIONS_VAR_H
5
6 #ifndef CDSLIB_OPT_OPTIONS_H
7 #   error <cds/opt/options.h> must be included instead of <cds/opt/make_options_var.h>
8 #endif
9
10 namespace cds { namespace opt {
11
12     //@cond
13     namespace details {
14         template <typename OptionList, typename Option>
15         struct do_pack
16         {
17             // Use "pack" member template to pack options
18             typedef typename Option::template pack<OptionList> type;
19         };
20
21         template <typename ...T> class typelist;
22
23         template <typename Typelist> struct typelist_head;
24         template <typename Head, typename ...Tail>
25         struct typelist_head< typelist<Head, Tail...> > {
26             typedef Head type;
27         };
28         template <typename Head>
29         struct typelist_head< typelist<Head> > {
30             typedef Head type;
31         };
32
33         template <typename Typelist> struct typelist_tail;
34         template <typename Head, typename ...Tail>
35         struct typelist_tail< typelist<Head, Tail...> > {
36             typedef typelist<Tail...> type;
37         };
38         template <typename Head>
39         struct typelist_tail< typelist<Head> > {
40             typedef typelist<> type;
41         };
42
43         template <typename OptionList, typename Typelist>
44         struct make_options_impl {
45             typedef typename make_options_impl<
46                 typename do_pack<
47                     OptionList,
48                     typename typelist_head< Typelist >::type
49                 >::type,
50                 typename typelist_tail<Typelist>::type
51             >::type type;
52         };
53
54         template <typename OptionList>
55         struct make_options_impl<OptionList, typelist<> > {
56             typedef OptionList type;
57         };
58     }   // namespace details
59     //@endcond
60
61     /// make_options metafunction
62     /** @headerfile cds/opt/options.h
63
64         The metafunction converts option list \p Options to traits structure.
65         The result of metafunction is \p type.
66
67         Template parameter \p OptionList is default option set (default traits).
68         \p Options is option list.
69     */
70     template <typename OptionList, typename... Options>
71     struct make_options {
72 #ifdef CDS_DOXYGEN_INVOKED
73         typedef implementation_defined type ;   ///< Result of the metafunction
74 #else
75         typedef typename details::make_options_impl< OptionList, details::typelist<Options...> >::type type;
76 #endif
77     };
78
79
80     // *****************************************************************
81     // find_type_traits metafunction
82     // *****************************************************************
83
84     //@cond
85     namespace details {
86         template <typename... Options>
87         struct find_type_traits_option;
88
89         template <>
90         struct find_type_traits_option<> {
91             typedef cds::opt::none  type;
92         };
93
94         template <typename Any>
95         struct find_type_traits_option< Any > {
96             typedef cds::opt::none type;
97         };
98
99         template <typename Any>
100         struct find_type_traits_option< cds::opt::type_traits< Any > > {
101             typedef Any type;
102         };
103
104         template <typename Any, typename... Options>
105         struct find_type_traits_option< cds::opt::type_traits< Any >, Options... > {
106             typedef Any type;
107         };
108
109         template <typename Any, typename... Options>
110         struct find_type_traits_option< Any, Options... > {
111             typedef typename find_type_traits_option< Options... >::type type;
112         };
113     } // namespace details
114     //@endcond
115
116     /// Metafunction to find opt::type_traits option in \p Options list
117     /** @headerfile cds/opt/options.h
118
119         If \p Options contains opt::type_traits option then it is the metafunction result.
120         Otherwise the result is \p DefaultOptons.
121     */
122     template <typename DefaultOptions, typename... Options>
123     struct find_type_traits {
124         typedef typename select_default< typename details::find_type_traits_option<Options...>::type, DefaultOptions>::type type ;  ///< Metafunction result
125     };
126
127
128     // *****************************************************************
129     // find_option metafunction
130     // *****************************************************************
131
132     //@cond
133     namespace details {
134         template <typename What, typename... Options>
135         struct find_option;
136
137         struct compare_ok;
138         struct compare_fail;
139
140         template <typename A, typename B>
141         struct compare_option
142         {
143             typedef compare_fail type;
144         };
145
146         template <template <typename> class Opt, typename A, typename B>
147         struct compare_option< Opt<A>, Opt<B> >
148         {
149             typedef compare_ok   type;
150         };
151
152         // Specializations for integral type of option
153 #define _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION( _type ) template <template <_type> class What, _type A, _type B> \
154         struct compare_option< What<A>, What<B> > { typedef compare_ok type ; };
155
156         // For user-defined enum types
157 #define CDS_DECLARE_FIND_OPTION_INTEGRAL_SPECIALIZATION( _type ) namespace cds { namespace opt { namespace details { _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(_type ) }}}
158
159         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(bool)
160         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(char)
161         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(unsigned char)
162         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(signed char)
163         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(short int)
164         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(unsigned short int)
165         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(int)
166         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(unsigned int)
167         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(long)
168         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(unsigned long)
169         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(long long)
170         _CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION(unsigned long long)
171
172
173         template <typename CompResult, typename Ok, typename Fail>
174         struct select_option
175         {
176             typedef Fail    type;
177         };
178
179         template <typename Ok, typename Fail>
180         struct select_option< compare_ok, Ok, Fail >
181         {
182             typedef Ok      type;
183         };
184
185         template <typename What>
186         struct find_option< What > {
187             typedef What    type;
188         };
189
190         template <typename What, typename Opt>
191         struct find_option< What, Opt > {
192             typedef typename select_option<
193                 typename compare_option< What, Opt >::type
194                 ,Opt
195                 ,What
196             >::type type;
197         };
198
199         template <typename What, typename Opt, typename... Options>
200         struct find_option< What, Opt, Options... > {
201             typedef typename select_option<
202                 typename compare_option< What, Opt >::type
203                 ,Opt
204                 ,typename find_option< What, Options... >::type
205             >::type type;
206         };
207     } // namespace details
208     //@endcond
209
210     /// Metafunction to find \p What option in \p Options list
211     /** @headerfile cds/opt/options.h
212
213         If \p Options contains \p What< Val > option for any \p Val then the result is \p What< Val >
214         Otherwise the result is \p What.
215
216         Example:
217         \code
218         #include <cds/opt/options.h>
219         namespace co = cds::opt;
220
221         struct default_tag;
222         struct tag_a;
223         struct tag_b;
224
225         // Find option co::tag.
226
227         // res1 is co::tag< tag_a >
228         typedef co::find_option< co::tag< default_tag >, co::gc< cds::gc::HP >, co::tag< tag_a > >::type res1;
229
230         // res2 is default co::tag< default_tag >
231         typedef co::find_option< co::tag< default_tag >, co::less< x >, co::hash< H > >::type res2;
232
233         // Multiple option co::tag. The first option is selected
234         // res3 is default co::tag< tag_a >
235         typedef co::find_option< co::tag< default_tag >, co::tag< tag_a >, co::tag< tag_b > >::type res3;
236
237         \endcode
238     */
239     template <typename What, typename... Options>
240     struct find_option {
241         typedef typename details::find_option<What, Options...>::type   type ;  ///< Metafunction result
242     };
243
244
245     // *****************************************************************
246     // select metafunction
247     // *****************************************************************
248
249     //@cond
250     namespace details {
251
252         template <typename What, typename... Pairs>
253         struct select;
254
255         template <typename What, typename Value>
256         struct select< What, What, Value>
257         {
258             typedef Value   type;
259         };
260
261         template <typename What, typename Tag, typename Value>
262         struct select<What, Tag, Value>
263         {
264             typedef What    type;
265         };
266
267         template <typename What, typename Value, typename... Pairs>
268         struct select< What, What, Value, Pairs...>
269         {
270             typedef Value   type;
271         };
272
273         template <typename What, typename Tag, typename Value, typename... Pairs>
274         struct select< What, Tag, Value, Pairs...>
275         {
276             typedef typename select<What, Pairs...>::type   type;
277         };
278     }   // namespace details
279     //@endcond
280
281     /// Select option metafunction
282     /** @headerfile cds/opt/options.h
283
284         Pseudocode:
285         \code
286         select <What, T1, R1, T2, R2, ... Tn, Rn> ::=
287             if What == T1 then return R1
288             if What == T2 then return R2
289             ...
290             if What == Tn then return Rn
291             else return What
292         \endcode
293     */
294     template <typename What, typename... Pairs>
295     struct select {
296         typedef typename details::select< What, Pairs...>::type  type    ;   ///< Metafunction result
297     };
298
299 }}  // namespace cds::opt
300
301 #endif // #ifndef CDSLIB_OPT_MAKE_OPTIONS_STD_H