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