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-2021 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 MSVC2015 Update 1 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 323