Chris@16: //----------------------------------------------------------------------------- Chris@16: // boost variant/variant_fwd.hpp header file Chris@16: // See http://www.boost.org for updates, documentation, and revision history. Chris@16: //----------------------------------------------------------------------------- Chris@16: // Chris@101: // Copyright (c) 2003 Eric Friedman, Itay Maman Chris@101: // Copyright (c) 2013 Antony Polukhin Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_VARIANT_VARIANT_FWD_HPP Chris@16: #define BOOST_VARIANT_VARIANT_FWD_HPP Chris@16: Chris@16: #include "boost/variant/detail/config.hpp" Chris@16: Chris@16: #include "boost/blank_fwd.hpp" Chris@16: #include "boost/mpl/arg.hpp" Chris@16: #include "boost/mpl/limits/arity.hpp" Chris@16: #include "boost/mpl/aux_/na.hpp" Chris@16: #include "boost/preprocessor/cat.hpp" Chris@16: #include "boost/preprocessor/enum.hpp" Chris@16: #include "boost/preprocessor/enum_params.hpp" Chris@16: #include "boost/preprocessor/enum_shifted_params.hpp" Chris@16: #include "boost/preprocessor/repeat.hpp" Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // macro BOOST_VARIANT_NO_REFERENCE_SUPPORT Chris@16: // Chris@16: // Defined if variant does not support references as bounded types. Chris@16: // Chris@16: #if defined(BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING) \ Chris@16: && !defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND) \ Chris@16: && !defined(BOOST_VARIANT_NO_REFERENCE_SUPPORT) Chris@16: # define BOOST_VARIANT_NO_REFERENCE_SUPPORT Chris@16: #endif Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // macro BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT Chris@16: // Chris@16: // Defined if variant does not support make_variant_over (see below). Chris@16: // Chris@16: #if defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) Chris@16: # define BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT Chris@16: #endif Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // macro BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT Chris@16: // Chris@16: // Defined if make_recursive_variant cannot be supported as documented. Chris@16: // Chris@16: // Note: Currently, MPL lambda facility is used as workaround if defined, and Chris@16: // so only types declared w/ MPL lambda workarounds will work. Chris@16: // Chris@16: Chris@16: #include "boost/variant/detail/substitute_fwd.hpp" Chris@16: Chris@16: #if defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) \ Chris@101: && !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT) Chris@16: # define BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT Chris@16: #endif Chris@16: Chris@101: Chris@101: /////////////////////////////////////////////////////////////////////////////// Chris@101: // macro BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES Chris@101: // Chris@101: Chris@101: /* Chris@101: GCC before 4.0 had no variadic tempaltes; Chris@101: GCC 4.6 has incomplete implementation of variadic templates. Chris@101: Chris@101: MSVC2013 has variadic templates, but they have issues. Chris@101: Chris@101: NOTE: Clang compiler defines __GNUC__ Chris@101: */ Chris@101: #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) \ Chris@101: || (!defined(__clang__) && defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)) \ Chris@101: || (defined(_MSC_VER) && (_MSC_VER <= 1900)) \ Chris@101: || defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) \ Chris@101: || defined (BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT) Chris@101: Chris@101: #ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES Chris@101: # define BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES Chris@101: #endif Chris@101: Chris@101: #endif Chris@101: Chris@101: #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) Chris@101: #include Chris@101: Chris@101: #define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_class class)( Chris@101: #define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_typename typename)( Chris@101: Chris@101: #define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_VARIADIC_class class... Chris@101: #define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_VARIADIC_typename typename... Chris@101: Chris@101: #define ARGS_VARIADER_1(x) x ## N... Chris@101: #define ARGS_VARIADER_2(x) BOOST_VARIANT_CLASS_OR_TYPENAME_TO_VARIADIC_ ## x ## N Chris@101: Chris@101: #define BOOST_VARIANT_MAKE_VARIADIC(sequence, x) BOOST_VARIANT_MAKE_VARIADIC_I(BOOST_PP_SEQ_SIZE(sequence), x) Chris@101: #define BOOST_VARIANT_MAKE_VARIADIC_I(argscount, x) BOOST_VARIANT_MAKE_VARIADIC_II(argscount, x) Chris@101: #define BOOST_VARIANT_MAKE_VARIADIC_II(argscount, orig) ARGS_VARIADER_ ## argscount(orig) Chris@101: Chris@101: /////////////////////////////////////////////////////////////////////////////// Chris@101: // BOOST_VARIANT_ENUM_PARAMS and BOOST_VARIANT_ENUM_SHIFTED_PARAMS Chris@101: // Chris@101: // Convenience macro for enumeration of variant params. Chris@101: // When variadic templates are available expands: Chris@101: // BOOST_VARIANT_ENUM_PARAMS(class Something) => class Something0, class... SomethingN Chris@101: // BOOST_VARIANT_ENUM_PARAMS(typename Something) => typename Something0, typename... SomethingN Chris@101: // BOOST_VARIANT_ENUM_PARAMS(Something) => Something0, SomethingN... Chris@101: // BOOST_VARIANT_ENUM_PARAMS(Something) => Something0, SomethingN... Chris@101: // BOOST_VARIANT_ENUM_SHIFTED_PARAMS(class Something) => class... SomethingN Chris@101: // BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename Something) => typename... SomethingN Chris@101: // BOOST_VARIANT_ENUM_SHIFTED_PARAMS(Something) => SomethingN... Chris@101: // BOOST_VARIANT_ENUM_SHIFTED_PARAMS(Something) => SomethingN... Chris@101: // Chris@101: // Rationale: Cleaner, simpler code for clients of variant library. Minimal Chris@101: // code modifications to move from C++03 to C++11. Chris@101: // Chris@101: // With BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES defined Chris@101: // will be used BOOST_VARIANT_ENUM_PARAMS and BOOST_VARIANT_ENUM_SHIFTED_PARAMS from below `#else` Chris@101: // Chris@101: Chris@101: #define BOOST_VARIANT_ENUM_PARAMS(x) \ Chris@101: x ## 0, \ Chris@101: BOOST_VARIANT_MAKE_VARIADIC( (BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_ ## x), x) \ Chris@101: /**/ Chris@101: Chris@101: #define BOOST_VARIANT_ENUM_SHIFTED_PARAMS(x) \ Chris@101: BOOST_VARIANT_MAKE_VARIADIC( (BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_ ## x), x) \ Chris@101: /**/ Chris@101: Chris@101: #else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) Chris@101: Chris@101: /////////////////////////////////////////////////////////////////////////////// Chris@101: // macro BOOST_VARIANT_LIMIT_TYPES Chris@101: // Chris@101: // Implementation-defined preprocessor symbol describing the actual Chris@101: // length of variant's pseudo-variadic template parameter list. Chris@101: // Chris@101: #include "boost/mpl/limits/list.hpp" Chris@101: #define BOOST_VARIANT_LIMIT_TYPES \ Chris@101: BOOST_MPL_LIMIT_LIST_SIZE Chris@101: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // macro BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY Chris@16: // Chris@16: // Exposes maximum allowed arity of class templates with recursive_variant Chris@16: // arguments. That is, Chris@16: // make_recursive_variant< ..., T<[1], recursive_variant_, ... [N]> >. Chris@16: // Chris@16: #include "boost/mpl/limits/arity.hpp" Chris@16: #define BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY \ Chris@16: BOOST_MPL_LIMIT_METAFUNCTION_ARITY Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // macro BOOST_VARIANT_ENUM_PARAMS Chris@16: // Chris@16: // Convenience macro for enumeration of BOOST_VARIANT_LIMIT_TYPES params. Chris@16: // Chris@16: // Rationale: Cleaner, simpler code for clients of variant library. Chris@16: // Chris@16: #define BOOST_VARIANT_ENUM_PARAMS( param ) \ Chris@16: BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, param) Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // macro BOOST_VARIANT_ENUM_SHIFTED_PARAMS Chris@16: // Chris@16: // Convenience macro for enumeration of BOOST_VARIANT_LIMIT_TYPES-1 params. Chris@16: // Chris@16: #define BOOST_VARIANT_ENUM_SHIFTED_PARAMS( param ) \ Chris@16: BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_VARIANT_LIMIT_TYPES, param) Chris@16: Chris@101: #endif // BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES workaround Chris@101: Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: namespace detail { namespace variant { Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) class void_ and class template convert_void Chris@16: // Chris@16: // Provides the mechanism by which void(NN) types are converted to Chris@16: // mpl::void_ (and thus can be passed to mpl::list). Chris@16: // Chris@16: // Rationale: This is particularly needed for the using-declarations Chris@16: // workaround (below), but also to avoid associating mpl namespace with Chris@16: // variant in argument dependent lookups (which used to happen because of Chris@16: // defaulting of template parameters to mpl::void_). Chris@16: // Chris@16: Chris@16: struct void_; Chris@16: Chris@16: template Chris@16: struct convert_void Chris@16: { Chris@16: typedef T type; Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct convert_void< void_ > Chris@16: { Chris@16: typedef mpl::na type; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (workaround) BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE Chris@16: // Chris@16: // Needed to work around compilers that don't support using-declaration Chris@16: // overloads. (See the variant::initializer workarounds below.) Chris@16: // Chris@16: Chris@16: #if defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) Chris@16: // (detail) tags voidNN -- NN defined on [0, BOOST_VARIANT_LIMIT_TYPES) Chris@16: // Chris@16: // Defines void types that are each unique and specializations of Chris@16: // convert_void that yields mpl::na for each voidNN type. Chris@16: // Chris@16: Chris@16: #define BOOST_VARIANT_DETAIL_DEFINE_VOID_N(z,N,_) \ Chris@16: struct BOOST_PP_CAT(void,N); \ Chris@16: \ Chris@16: template <> \ Chris@16: struct convert_void< BOOST_PP_CAT(void,N) > \ Chris@16: { \ Chris@16: typedef mpl::na type; \ Chris@16: }; \ Chris@16: /**/ Chris@16: Chris@16: BOOST_PP_REPEAT( Chris@16: BOOST_VARIANT_LIMIT_TYPES Chris@16: , BOOST_VARIANT_DETAIL_DEFINE_VOID_N Chris@16: , _ Chris@16: ) Chris@16: Chris@16: #undef BOOST_VARIANT_DETAIL_DEFINE_VOID_N Chris@16: Chris@16: #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround Chris@16: Chris@16: }} // namespace detail::variant Chris@16: Chris@101: #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) Chris@101: # define BOOST_VARIANT_AUX_DECLARE_PARAMS BOOST_VARIANT_ENUM_PARAMS(typename T) Chris@101: #else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) Chris@101: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) macro BOOST_VARIANT_AUX_DECLARE_PARAM Chris@16: // Chris@16: // Template parameter list for variant and recursive_variant declarations. Chris@16: // Chris@16: Chris@16: #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) Chris@16: Chris@16: # define BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL(z, N, T) \ Chris@16: typename BOOST_PP_CAT(T,N) = detail::variant::void_ \ Chris@16: /**/ Chris@16: Chris@16: #else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) Chris@16: Chris@16: # define BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL(z, N, T) \ Chris@16: typename BOOST_PP_CAT(T,N) = BOOST_PP_CAT(detail::variant::void,N) \ Chris@16: /**/ Chris@16: Chris@16: #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround Chris@16: Chris@16: #define BOOST_VARIANT_AUX_DECLARE_PARAMS \ Chris@16: BOOST_PP_ENUM( \ Chris@16: BOOST_VARIANT_LIMIT_TYPES \ Chris@16: , BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL \ Chris@16: , T \ Chris@16: ) \ Chris@16: /**/ Chris@16: Chris@101: #endif // BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES workaround Chris@101: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // class template variant (concept inspired by Andrei Alexandrescu) Chris@16: // Chris@16: // Efficient, type-safe bounded discriminated union. Chris@16: // Chris@16: // Preconditions: Chris@16: // - Each type must be unique. Chris@16: // - No type may be const-qualified. Chris@16: // Chris@16: // Proper declaration form: Chris@16: // variant (where types is a type-sequence) Chris@16: // or Chris@16: // variant (where T0 is NOT a type-sequence) Chris@16: // Chris@16: template < BOOST_VARIANT_AUX_DECLARE_PARAMS > class variant; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // metafunction make_recursive_variant Chris@16: // Chris@16: // Exposes a boost::variant with recursive_variant_ tags (below) substituted Chris@16: // with the variant itself (wrapped as needed with boost::recursive_wrapper). Chris@16: // Chris@16: template < BOOST_VARIANT_AUX_DECLARE_PARAMS > struct make_recursive_variant; Chris@16: Chris@16: #undef BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL Chris@16: #undef BOOST_VARIANT_AUX_DECLARE_PARAMS Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // type recursive_variant_ Chris@16: // Chris@16: // Tag type indicates where recursive variant substitution should occur. Chris@16: // Chris@16: #if !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT) Chris@16: struct recursive_variant_ {}; Chris@16: #else Chris@16: typedef mpl::arg<1> recursive_variant_; Chris@16: #endif Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // metafunction make_variant_over Chris@16: // Chris@16: // Result is a variant w/ types of the specified type sequence. Chris@16: // Chris@16: template struct make_variant_over; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // metafunction make_recursive_variant_over Chris@16: // Chris@16: // Result is a recursive variant w/ types of the specified type sequence. Chris@16: // Chris@16: template struct make_recursive_variant_over; Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #endif // BOOST_VARIANT_VARIANT_FWD_HPP