williamr@2: //----------------------------------------------------------------------------- williamr@2: // boost variant/variant_fwd.hpp header file williamr@2: // See http://www.boost.org for updates, documentation, and revision history. williamr@2: //----------------------------------------------------------------------------- williamr@2: // williamr@2: // Copyright (c) 2003 williamr@2: // Eric Friedman, Itay Maman williamr@2: // williamr@2: // Distributed under the Boost Software License, Version 1.0. (See williamr@2: // accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: williamr@2: #ifndef BOOST_VARIANT_VARIANT_FWD_HPP williamr@2: #define BOOST_VARIANT_VARIANT_FWD_HPP williamr@2: williamr@2: #include "boost/variant/detail/config.hpp" williamr@2: williamr@2: #include "boost/blank_fwd.hpp" williamr@2: #include "boost/mpl/arg.hpp" williamr@2: #include "boost/mpl/limits/arity.hpp" williamr@2: #include "boost/mpl/aux_/na.hpp" williamr@2: #include "boost/preprocessor/cat.hpp" williamr@2: #include "boost/preprocessor/enum.hpp" williamr@2: #include "boost/preprocessor/enum_params.hpp" williamr@2: #include "boost/preprocessor/enum_shifted_params.hpp" williamr@2: #include "boost/preprocessor/repeat.hpp" williamr@2: williamr@2: /////////////////////////////////////////////////////////////////////////////// williamr@2: // macro BOOST_VARIANT_LIMIT_TYPES williamr@2: // williamr@2: // Implementation-defined preprocessor symbol describing the actual williamr@2: // length of variant's pseudo-variadic template parameter list. williamr@2: // williamr@2: #include "boost/mpl/limits/list.hpp" williamr@2: #define BOOST_VARIANT_LIMIT_TYPES \ williamr@2: BOOST_MPL_LIMIT_LIST_SIZE williamr@2: williamr@2: /////////////////////////////////////////////////////////////////////////////// williamr@2: // macro BOOST_VARIANT_NO_REFERENCE_SUPPORT williamr@2: // williamr@2: // Defined if variant does not support references as bounded types. williamr@2: // williamr@2: #if defined(BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING) \ williamr@2: && !defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND) \ williamr@2: && !defined(BOOST_VARIANT_NO_REFERENCE_SUPPORT) williamr@2: # define BOOST_VARIANT_NO_REFERENCE_SUPPORT williamr@2: #endif williamr@2: williamr@2: /////////////////////////////////////////////////////////////////////////////// williamr@2: // macro BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT williamr@2: // williamr@2: // Defined if variant does not support make_variant_over (see below). williamr@2: // williamr@2: #if defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) williamr@2: # define BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT williamr@2: #endif williamr@2: williamr@2: /////////////////////////////////////////////////////////////////////////////// williamr@2: // macro BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT williamr@2: // williamr@2: // Defined if make_recursive_variant cannot be supported as documented. williamr@2: // williamr@2: // Note: Currently, MPL lambda facility is used as workaround if defined, and williamr@2: // so only types declared w/ MPL lambda workarounds will work. williamr@2: // williamr@2: williamr@2: #include "boost/variant/detail/substitute_fwd.hpp" williamr@2: williamr@2: #if defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) \ williamr@2: && !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT) williamr@2: # define BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT williamr@2: #endif williamr@2: williamr@2: /////////////////////////////////////////////////////////////////////////////// williamr@2: // macro BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY williamr@2: // williamr@2: // Exposes maximum allowed arity of class templates with recursive_variant williamr@2: // arguments. That is, williamr@2: // make_recursive_variant< ..., T<[1], recursive_variant_, ... [N]> >. williamr@2: // williamr@2: #include "boost/mpl/limits/arity.hpp" williamr@2: #define BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY \ williamr@2: BOOST_MPL_LIMIT_METAFUNCTION_ARITY williamr@2: williamr@2: /////////////////////////////////////////////////////////////////////////////// williamr@2: // macro BOOST_VARIANT_ENUM_PARAMS williamr@2: // williamr@2: // Convenience macro for enumeration of BOOST_VARIANT_LIMIT_TYPES params. williamr@2: // williamr@2: // Rationale: Cleaner, simpler code for clients of variant library. williamr@2: // williamr@2: #define BOOST_VARIANT_ENUM_PARAMS( param ) \ williamr@2: BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, param) williamr@2: williamr@2: /////////////////////////////////////////////////////////////////////////////// williamr@2: // macro BOOST_VARIANT_ENUM_SHIFTED_PARAMS williamr@2: // williamr@2: // Convenience macro for enumeration of BOOST_VARIANT_LIMIT_TYPES-1 params. williamr@2: // williamr@2: #define BOOST_VARIANT_ENUM_SHIFTED_PARAMS( param ) \ williamr@2: BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_VARIANT_LIMIT_TYPES, param) williamr@2: williamr@2: williamr@2: namespace boost { williamr@2: williamr@2: namespace detail { namespace variant { williamr@2: williamr@2: /////////////////////////////////////////////////////////////////////////////// williamr@2: // (detail) class void_ and class template convert_void williamr@2: // williamr@2: // Provides the mechanism by which void(NN) types are converted to williamr@2: // mpl::void_ (and thus can be passed to mpl::list). williamr@2: // williamr@2: // Rationale: This is particularly needed for the using-declarations williamr@2: // workaround (below), but also to avoid associating mpl namespace with williamr@2: // variant in argument dependent lookups (which used to happen because of williamr@2: // defaulting of template parameters to mpl::void_). williamr@2: // williamr@2: williamr@2: struct void_; williamr@2: williamr@2: template williamr@2: struct convert_void williamr@2: { williamr@2: typedef T type; williamr@2: }; williamr@2: williamr@2: template <> williamr@2: struct convert_void< void_ > williamr@2: { williamr@2: typedef mpl::na type; williamr@2: }; williamr@2: williamr@2: /////////////////////////////////////////////////////////////////////////////// williamr@2: // (workaround) BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE williamr@2: // williamr@2: // Needed to work around compilers that don't support using-declaration williamr@2: // overloads. (See the variant::initializer workarounds below.) williamr@2: // williamr@2: williamr@2: #if defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) williamr@2: williamr@2: // (detail) tags voidNN -- NN defined on [0, BOOST_VARIANT_LIMIT_TYPES) williamr@2: // williamr@2: // Defines void types that are each unique and specializations of williamr@2: // convert_void that yields mpl::na for each voidNN type. williamr@2: // williamr@2: williamr@2: #define BOOST_VARIANT_DETAIL_DEFINE_VOID_N(z,N,_) \ williamr@2: struct BOOST_PP_CAT(void,N); \ williamr@2: \ williamr@2: template <> \ williamr@2: struct convert_void< BOOST_PP_CAT(void,N) > \ williamr@2: { \ williamr@2: typedef mpl::na type; \ williamr@2: }; \ williamr@2: /**/ williamr@2: williamr@2: BOOST_PP_REPEAT( williamr@2: BOOST_VARIANT_LIMIT_TYPES williamr@2: , BOOST_VARIANT_DETAIL_DEFINE_VOID_N williamr@2: , _ williamr@2: ) williamr@2: williamr@2: #undef BOOST_VARIANT_DETAIL_DEFINE_VOID_N williamr@2: williamr@2: #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround williamr@2: williamr@2: }} // namespace detail::variant williamr@2: williamr@2: /////////////////////////////////////////////////////////////////////////////// williamr@2: // (detail) macro BOOST_VARIANT_AUX_DECLARE_PARAM williamr@2: // williamr@2: // Template parameter list for variant and recursive_variant declarations. williamr@2: // williamr@2: williamr@2: #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) williamr@2: williamr@2: # define BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL(z, N, T) \ williamr@2: typename BOOST_PP_CAT(T,N) = detail::variant::void_ \ williamr@2: /**/ williamr@2: williamr@2: #else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) williamr@2: williamr@2: # define BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL(z, N, T) \ williamr@2: typename BOOST_PP_CAT(T,N) = BOOST_PP_CAT(detail::variant::void,N) \ williamr@2: /**/ williamr@2: williamr@2: #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround williamr@2: williamr@2: #define BOOST_VARIANT_AUX_DECLARE_PARAMS \ williamr@2: BOOST_PP_ENUM( \ williamr@2: BOOST_VARIANT_LIMIT_TYPES \ williamr@2: , BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL \ williamr@2: , T \ williamr@2: ) \ williamr@2: /**/ williamr@2: williamr@2: /////////////////////////////////////////////////////////////////////////////// williamr@2: // class template variant (concept inspired by Andrei Alexandrescu) williamr@2: // williamr@2: // Efficient, type-safe bounded discriminated union. williamr@2: // williamr@2: // Preconditions: williamr@2: // - Each type must be unique. williamr@2: // - No type may be const-qualified. williamr@2: // williamr@2: // Proper declaration form: williamr@2: // variant (where types is a type-sequence) williamr@2: // or williamr@2: // variant (where T0 is NOT a type-sequence) williamr@2: // williamr@2: template < BOOST_VARIANT_AUX_DECLARE_PARAMS > class variant; williamr@2: williamr@2: /////////////////////////////////////////////////////////////////////////////// williamr@2: // metafunction make_recursive_variant williamr@2: // williamr@2: // Exposes a boost::variant with recursive_variant_ tags (below) substituted williamr@2: // with the variant itself (wrapped as needed with boost::recursive_wrapper). williamr@2: // williamr@2: template < BOOST_VARIANT_AUX_DECLARE_PARAMS > struct make_recursive_variant; williamr@2: williamr@2: #undef BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL williamr@2: #undef BOOST_VARIANT_AUX_DECLARE_PARAMS williamr@2: williamr@2: /////////////////////////////////////////////////////////////////////////////// williamr@2: // type recursive_variant_ williamr@2: // williamr@2: // Tag type indicates where recursive variant substitution should occur. williamr@2: // williamr@2: #if !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT) williamr@2: struct recursive_variant_; williamr@2: #else williamr@2: typedef mpl::arg<1> recursive_variant_; williamr@2: #endif williamr@2: williamr@2: /////////////////////////////////////////////////////////////////////////////// williamr@2: // metafunction make_variant_over williamr@2: // williamr@2: // Result is a variant w/ types of the specified type sequence. williamr@2: // williamr@2: template struct make_variant_over; williamr@2: williamr@2: /////////////////////////////////////////////////////////////////////////////// williamr@2: // metafunction make_recursive_variant_over williamr@2: // williamr@2: // Result is a recursive variant w/ types of the specified type sequence. williamr@2: // williamr@2: template struct make_recursive_variant_over; williamr@2: williamr@2: } // namespace boost williamr@2: williamr@2: #endif // BOOST_VARIANT_VARIANT_FWD_HPP