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