]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | //----------------------------------------------------------------------------- |
2 | // boost variant/variant_fwd.hpp header file | |
3 | // See http://www.boost.org for updates, documentation, and revision history. | |
4 | //----------------------------------------------------------------------------- | |
5 | // | |
6 | // Copyright (c) 2003 Eric Friedman, Itay Maman | |
7 | // Copyright (c) 2013-2016 Antony Polukhin | |
8 | // | |
9 | // Distributed under the Boost Software License, Version 1.0. (See | |
10 | // accompanying file LICENSE_1_0.txt or copy at | |
11 | // http://www.boost.org/LICENSE_1_0.txt) | |
12 | ||
13 | #ifndef BOOST_VARIANT_VARIANT_FWD_HPP | |
14 | #define BOOST_VARIANT_VARIANT_FWD_HPP | |
15 | ||
16 | #include <boost/variant/detail/config.hpp> | |
17 | ||
18 | #include <boost/blank_fwd.hpp> | |
19 | #include <boost/mpl/arg.hpp> | |
20 | #include <boost/mpl/limits/arity.hpp> | |
21 | #include <boost/mpl/aux_/na.hpp> | |
22 | #include <boost/preprocessor/cat.hpp> | |
23 | #include <boost/preprocessor/enum.hpp> | |
24 | #include <boost/preprocessor/enum_params.hpp> | |
25 | #include <boost/preprocessor/enum_shifted_params.hpp> | |
26 | #include <boost/preprocessor/repeat.hpp> | |
27 | ||
28 | /////////////////////////////////////////////////////////////////////////////// | |
29 | // macro BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT | |
30 | // | |
31 | // Defined if variant does not support make_variant_over (see below). | |
32 | // | |
33 | #if defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) | |
34 | # define BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT | |
35 | #endif | |
36 | ||
37 | /////////////////////////////////////////////////////////////////////////////// | |
38 | // macro BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT | |
39 | // | |
40 | // Defined if make_recursive_variant cannot be supported as documented. | |
41 | // | |
42 | // Note: Currently, MPL lambda facility is used as workaround if defined, and | |
43 | // so only types declared w/ MPL lambda workarounds will work. | |
44 | // | |
45 | ||
46 | #include <boost/variant/detail/substitute_fwd.hpp> | |
47 | ||
48 | #if defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) \ | |
49 | && !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT) | |
50 | # define BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT | |
51 | #endif | |
52 | ||
53 | ||
54 | /////////////////////////////////////////////////////////////////////////////// | |
55 | // macro BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES | |
56 | // | |
57 | ||
58 | /* | |
59 | GCC before 4.0 had no variadic tempaltes; | |
60 | GCC 4.6 has incomplete implementation of variadic templates. | |
61 | ||
62 | MSVC2013 has variadic templates, but they have issues. | |
63 | ||
64 | NOTE: Clang compiler defines __GNUC__ | |
65 | */ | |
66 | #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) \ | |
67 | || (!defined(__clang__) && defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)) \ | |
68 | || (defined(_MSC_VER) && (_MSC_VER <= 1900)) \ | |
69 | || defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) \ | |
70 | || defined (BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT) | |
71 | ||
72 | #ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES | |
73 | # define BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES | |
74 | #endif | |
75 | ||
76 | #endif | |
77 | ||
78 | #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) | |
79 | #include <boost/preprocessor/seq/size.hpp> | |
80 | ||
81 | #define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_class class)( | |
82 | #define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_typename typename)( | |
83 | ||
84 | #define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_VARIADIC_class class... | |
85 | #define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_VARIADIC_typename typename... | |
86 | ||
87 | #define ARGS_VARIADER_1(x) x ## N... | |
88 | #define ARGS_VARIADER_2(x) BOOST_VARIANT_CLASS_OR_TYPENAME_TO_VARIADIC_ ## x ## N | |
89 | ||
90 | #define BOOST_VARIANT_MAKE_VARIADIC(sequence, x) BOOST_VARIANT_MAKE_VARIADIC_I(BOOST_PP_SEQ_SIZE(sequence), x) | |
91 | #define BOOST_VARIANT_MAKE_VARIADIC_I(argscount, x) BOOST_VARIANT_MAKE_VARIADIC_II(argscount, x) | |
92 | #define BOOST_VARIANT_MAKE_VARIADIC_II(argscount, orig) ARGS_VARIADER_ ## argscount(orig) | |
93 | ||
94 | /////////////////////////////////////////////////////////////////////////////// | |
95 | // BOOST_VARIANT_ENUM_PARAMS and BOOST_VARIANT_ENUM_SHIFTED_PARAMS | |
96 | // | |
97 | // Convenience macro for enumeration of variant params. | |
98 | // When variadic templates are available expands: | |
99 | // BOOST_VARIANT_ENUM_PARAMS(class Something) => class Something0, class... SomethingN | |
100 | // BOOST_VARIANT_ENUM_PARAMS(typename Something) => typename Something0, typename... SomethingN | |
101 | // BOOST_VARIANT_ENUM_PARAMS(Something) => Something0, SomethingN... | |
102 | // BOOST_VARIANT_ENUM_PARAMS(Something) => Something0, SomethingN... | |
103 | // BOOST_VARIANT_ENUM_SHIFTED_PARAMS(class Something) => class... SomethingN | |
104 | // BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename Something) => typename... SomethingN | |
105 | // BOOST_VARIANT_ENUM_SHIFTED_PARAMS(Something) => SomethingN... | |
106 | // BOOST_VARIANT_ENUM_SHIFTED_PARAMS(Something) => SomethingN... | |
107 | // | |
108 | // Rationale: Cleaner, simpler code for clients of variant library. Minimal | |
109 | // code modifications to move from C++03 to C++11. | |
110 | // | |
111 | // With BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES defined | |
112 | // will be used BOOST_VARIANT_ENUM_PARAMS and BOOST_VARIANT_ENUM_SHIFTED_PARAMS from below `#else` | |
113 | // | |
114 | ||
115 | #define BOOST_VARIANT_ENUM_PARAMS(x) \ | |
116 | x ## 0, \ | |
117 | BOOST_VARIANT_MAKE_VARIADIC( (BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_ ## x), x) \ | |
118 | /**/ | |
119 | ||
120 | #define BOOST_VARIANT_ENUM_SHIFTED_PARAMS(x) \ | |
121 | BOOST_VARIANT_MAKE_VARIADIC( (BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_ ## x), x) \ | |
122 | /**/ | |
123 | ||
124 | #else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) | |
125 | ||
126 | /////////////////////////////////////////////////////////////////////////////// | |
127 | // macro BOOST_VARIANT_LIMIT_TYPES | |
128 | // | |
129 | // Implementation-defined preprocessor symbol describing the actual | |
130 | // length of variant's pseudo-variadic template parameter list. | |
131 | // | |
132 | #include <boost/mpl/limits/list.hpp> | |
133 | #define BOOST_VARIANT_LIMIT_TYPES \ | |
134 | BOOST_MPL_LIMIT_LIST_SIZE | |
135 | ||
136 | /////////////////////////////////////////////////////////////////////////////// | |
137 | // macro BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY | |
138 | // | |
139 | // Exposes maximum allowed arity of class templates with recursive_variant | |
140 | // arguments. That is, | |
141 | // make_recursive_variant< ..., T<[1], recursive_variant_, ... [N]> >. | |
142 | // | |
143 | #include <boost/mpl/limits/arity.hpp> | |
144 | #define BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY \ | |
145 | BOOST_MPL_LIMIT_METAFUNCTION_ARITY | |
146 | ||
147 | /////////////////////////////////////////////////////////////////////////////// | |
148 | // macro BOOST_VARIANT_ENUM_PARAMS | |
149 | // | |
150 | // Convenience macro for enumeration of BOOST_VARIANT_LIMIT_TYPES params. | |
151 | // | |
152 | // Rationale: Cleaner, simpler code for clients of variant library. | |
153 | // | |
154 | #define BOOST_VARIANT_ENUM_PARAMS( param ) \ | |
155 | BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, param) | |
156 | ||
157 | /////////////////////////////////////////////////////////////////////////////// | |
158 | // macro BOOST_VARIANT_ENUM_SHIFTED_PARAMS | |
159 | // | |
160 | // Convenience macro for enumeration of BOOST_VARIANT_LIMIT_TYPES-1 params. | |
161 | // | |
162 | #define BOOST_VARIANT_ENUM_SHIFTED_PARAMS( param ) \ | |
163 | BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_VARIANT_LIMIT_TYPES, param) | |
164 | ||
165 | #endif // BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES workaround | |
166 | ||
167 | ||
168 | namespace boost { | |
169 | ||
170 | namespace detail { namespace variant { | |
171 | ||
172 | /////////////////////////////////////////////////////////////////////////////// | |
173 | // (detail) class void_ and class template convert_void | |
174 | // | |
175 | // Provides the mechanism by which void(NN) types are converted to | |
176 | // mpl::void_ (and thus can be passed to mpl::list). | |
177 | // | |
178 | // Rationale: This is particularly needed for the using-declarations | |
179 | // workaround (below), but also to avoid associating mpl namespace with | |
180 | // variant in argument dependent lookups (which used to happen because of | |
181 | // defaulting of template parameters to mpl::void_). | |
182 | // | |
183 | ||
184 | struct void_; | |
185 | ||
186 | template <typename T> | |
187 | struct convert_void | |
188 | { | |
189 | typedef T type; | |
190 | }; | |
191 | ||
192 | template <> | |
193 | struct convert_void< void_ > | |
194 | { | |
195 | typedef mpl::na type; | |
196 | }; | |
197 | ||
198 | /////////////////////////////////////////////////////////////////////////////// | |
199 | // (workaround) BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE | |
200 | // | |
201 | // Needed to work around compilers that don't support using-declaration | |
202 | // overloads. (See the variant::initializer workarounds below.) | |
203 | // | |
204 | ||
205 | #if defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) | |
206 | // (detail) tags voidNN -- NN defined on [0, BOOST_VARIANT_LIMIT_TYPES) | |
207 | // | |
208 | // Defines void types that are each unique and specializations of | |
209 | // convert_void that yields mpl::na for each voidNN type. | |
210 | // | |
211 | ||
212 | #define BOOST_VARIANT_DETAIL_DEFINE_VOID_N(z,N,_) \ | |
213 | struct BOOST_PP_CAT(void,N); \ | |
214 | \ | |
215 | template <> \ | |
216 | struct convert_void< BOOST_PP_CAT(void,N) > \ | |
217 | { \ | |
218 | typedef mpl::na type; \ | |
219 | }; \ | |
220 | /**/ | |
221 | ||
222 | BOOST_PP_REPEAT( | |
223 | BOOST_VARIANT_LIMIT_TYPES | |
224 | , BOOST_VARIANT_DETAIL_DEFINE_VOID_N | |
225 | , _ | |
226 | ) | |
227 | ||
228 | #undef BOOST_VARIANT_DETAIL_DEFINE_VOID_N | |
229 | ||
230 | #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround | |
231 | ||
232 | }} // namespace detail::variant | |
233 | ||
234 | #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) | |
235 | # define BOOST_VARIANT_AUX_DECLARE_PARAMS BOOST_VARIANT_ENUM_PARAMS(typename T) | |
236 | #else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) | |
237 | ||
238 | /////////////////////////////////////////////////////////////////////////////// | |
239 | // (detail) macro BOOST_VARIANT_AUX_DECLARE_PARAM | |
240 | // | |
241 | // Template parameter list for variant and recursive_variant declarations. | |
242 | // | |
243 | ||
244 | #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) | |
245 | ||
246 | # define BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL(z, N, T) \ | |
247 | typename BOOST_PP_CAT(T,N) = detail::variant::void_ \ | |
248 | /**/ | |
249 | ||
250 | #else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) | |
251 | ||
252 | # define BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL(z, N, T) \ | |
253 | typename BOOST_PP_CAT(T,N) = BOOST_PP_CAT(detail::variant::void,N) \ | |
254 | /**/ | |
255 | ||
256 | #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround | |
257 | ||
258 | #define BOOST_VARIANT_AUX_DECLARE_PARAMS \ | |
259 | BOOST_PP_ENUM( \ | |
260 | BOOST_VARIANT_LIMIT_TYPES \ | |
261 | , BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL \ | |
262 | , T \ | |
263 | ) \ | |
264 | /**/ | |
265 | ||
266 | #endif // BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES workaround | |
267 | ||
268 | /////////////////////////////////////////////////////////////////////////////// | |
269 | // class template variant (concept inspired by Andrei Alexandrescu) | |
270 | // | |
271 | // Efficient, type-safe bounded discriminated union. | |
272 | // | |
273 | // Preconditions: | |
274 | // - Each type must be unique. | |
275 | // - No type may be const-qualified. | |
276 | // | |
277 | // Proper declaration form: | |
278 | // variant<types> (where types is a type-sequence) | |
279 | // or | |
280 | // variant<T0,T1,...,Tn> (where T0 is NOT a type-sequence) | |
281 | // | |
282 | template < BOOST_VARIANT_AUX_DECLARE_PARAMS > class variant; | |
283 | ||
284 | /////////////////////////////////////////////////////////////////////////////// | |
285 | // metafunction make_recursive_variant | |
286 | // | |
287 | // Exposes a boost::variant with recursive_variant_ tags (below) substituted | |
288 | // with the variant itself (wrapped as needed with boost::recursive_wrapper). | |
289 | // | |
290 | template < BOOST_VARIANT_AUX_DECLARE_PARAMS > struct make_recursive_variant; | |
291 | ||
292 | #undef BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL | |
293 | #undef BOOST_VARIANT_AUX_DECLARE_PARAMS | |
294 | ||
295 | /////////////////////////////////////////////////////////////////////////////// | |
296 | // type recursive_variant_ | |
297 | // | |
298 | // Tag type indicates where recursive variant substitution should occur. | |
299 | // | |
300 | #if !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT) | |
301 | struct recursive_variant_ {}; | |
302 | #else | |
303 | typedef mpl::arg<1> recursive_variant_; | |
304 | #endif | |
305 | ||
306 | /////////////////////////////////////////////////////////////////////////////// | |
307 | // metafunction make_variant_over | |
308 | // | |
309 | // Result is a variant w/ types of the specified type sequence. | |
310 | // | |
311 | template <typename Types> struct make_variant_over; | |
312 | ||
313 | /////////////////////////////////////////////////////////////////////////////// | |
314 | // metafunction make_recursive_variant_over | |
315 | // | |
316 | // Result is a recursive variant w/ types of the specified type sequence. | |
317 | // | |
318 | template <typename Types> struct make_recursive_variant_over; | |
319 | ||
320 | } // namespace boost | |
321 | ||
322 | #endif // BOOST_VARIANT_VARIANT_FWD_HPP |