2
0
mirror of https://github.com/boostorg/variant.git synced 2026-02-17 14:12:12 +00:00

Dramatically reduced overhead caused by recursive_variant implementation for non-recursive variants.

[SVN r19720]
This commit is contained in:
Eric Friedman
2003-08-21 07:16:09 +00:00
parent 14f6f4aa99
commit dbcae544b0
8 changed files with 696 additions and 324 deletions

View File

@@ -0,0 +1,222 @@
#if !defined(BOOST_PP_IS_ITERATING)
///// header body
//-----------------------------------------------------------------------------
// boost variant/detail/enable_recursive.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_HPP
#define BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_HPP
#include "boost/mpl/aux_/config/ctps.hpp"
#include "boost/variant/detail/enable_recursive_fwd.hpp"
#include "boost/variant/variant_fwd.hpp"
#if !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
# include "boost/mpl/aux_/lambda_arity_param.hpp"
# include "boost/mpl/aux_/template_arity.hpp"
# include "boost/mpl/aux_/preprocessor/params.hpp"
# include "boost/mpl/aux_/preprocessor/repeat.hpp"
# include "boost/mpl/int_fwd.hpp"
# include "boost/preprocessor/cat.hpp"
# include "boost/preprocessor/arithmetic/inc.hpp"
# include "boost/preprocessor/iterate.hpp"
#else
# include "boost/mpl/apply.hpp"
# include "boost/mpl/apply_if.hpp"
# include "boost/mpl/lambda.hpp"
#endif
#include "boost/mpl/bool_fwd.hpp"
#include "boost/mpl/if.hpp"
#include "boost/mpl/or.hpp"
#include "boost/type_traits/is_same.hpp"
#include "boost/incomplete.hpp"
namespace boost {
namespace detail { namespace variant {
///////////////////////////////////////////////////////////////////////////////
// (detail) class specialization template enable_recursive_impl
//
// Performs recursive variant substitution.
//
#if !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
template <
typename T, typename RecursiveVariant
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(
typename Arity = mpl::int_< mpl::aux::template_arity<T>::value >
)
>
struct enable_recursive_impl
{
typedef T type;
};
template <typename RecursiveVariant>
struct enable_recursive_impl< recursive_variant_, RecursiveVariant >
{
typedef RecursiveVariant type;
};
#define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEF_IMPL(N) \
typedef typename enable_recursive_impl< \
BOOST_PP_CAT(U,N), RecursiveVariant \
>::type BOOST_PP_CAT(u,N); \
/**/
#define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEF(z, N, _) \
BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEF_IMPL( BOOST_PP_INC(N) ) \
/**/
#define BOOST_PP_ITERATION_LIMITS (1,BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY)
#define BOOST_PP_FILENAME_1 "boost/variant/detail/enable_recursive.hpp"
#include BOOST_PP_ITERATE()
#undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEF_IMPL
#undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEF
#else // defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
template <typename T, typename U1>
struct rebind1
{
private:
typedef typename mpl::lambda<
mpl::identity<T>
>::type le_;
public:
typedef typename mpl::apply_if<
is_same< le_, mpl::identity<T> >
, le_ // identity<T>
, mpl::apply1<le_, U1>
>::type type;
};
template <typename T, typename RecursiveVariant>
struct enable_recursive_impl
: rebind1< T,RecursiveVariant >
{
};
#endif // !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction enable_recursive
//
// Attempts recursive variant substitution and wraps with boost::incomplete
// if substituion occurs *and* NoWrapper is false_.
//
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <typename T, typename RecursiveVariant, typename NoWrapper>
struct enable_recursive
: enable_recursive_impl<T,RecursiveVariant>
{
};
template <typename T, typename RecursiveVariant>
struct enable_recursive< T,RecursiveVariant,mpl::false_ >
{
private: // helpers, for metafunction result (below)
typedef typename enable_recursive_impl<T,RecursiveVariant>::type t_;
public: // metafunction result
// [Wrap with incomplete only if rebind really changed something:]
typedef typename mpl::if_<
is_same< t_,T >
, t_
, boost::incomplete<t_>
>::type type;
};
#else // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <typename T, typename RecursiveVariant, typename NoWrapper>
struct enable_recursive
{
private: // helpers, for metafunction result (below)
typedef typename enable_recursive_impl<T,RecursiveVariant>::type t_;
public: // metafunction result
// [Wrap with incomplete only if rebind really changed something:]
typedef typename mpl::if_<
mpl::or_< NoWrapper, is_same< t_,T > >
, t_
, boost::incomplete<t_>
>::type type;
};
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION workaround
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction class quoted_enable_recursive
//
// Same behavior as enable_recursive metafunction (see above).
//
template <typename RecursiveVariant, typename NoWrapper>
struct quoted_enable_recursive
{
template <typename T>
struct apply
: enable_recursive<T, RecursiveVariant, NoWrapper>
{
};
};
}} // namespace detail::variant
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_HPP
///// iteration, depth == 1
#elif BOOST_PP_ITERATION_DEPTH() == 1
#define i BOOST_PP_FRAME_ITERATION(1)
template <
template < BOOST_MPL_PP_PARAMS(i,typename P) > class T
, BOOST_MPL_PP_PARAMS(i,typename U)
, typename RecursiveVariant
>
struct enable_recursive_impl<
T< BOOST_MPL_PP_PARAMS(i,U) >
, RecursiveVariant
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<( i )>)
>
{
private:
BOOST_MPL_PP_REPEAT(i, BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEF, _)
public:
typedef T< BOOST_MPL_PP_PARAMS(i,u) > type;
};
#undef i
#endif // BOOST_PP_IS_ITERATING

View File

@@ -0,0 +1,119 @@
//-----------------------------------------------------------------------------
// boost variant/detail/enable_recursive_fwd.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_FWD_HPP
#define BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_FWD_HPP
#include "boost/mpl/aux_/config/ctps.hpp"
#include "boost/mpl/bool_fwd.hpp"
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
# include "boost/mpl/bool.hpp"
#else
# include "boost/type_traits/is_base_and_derived.hpp"
#endif
namespace boost {
namespace detail { namespace variant {
///////////////////////////////////////////////////////////////////////////////
// (detail) tag recursive_flag
//
// Signifies that the variant should perform recursive substituion.
//
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <typename T>
struct recursive_flag
{
typedef T type;
};
#else // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
struct recursive_flag_tag
{
};
template <typename T>
struct recursive_flag
: recursive_flag_tag
{
typedef T type;
};
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION workaround
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction is_recursive_flag
//
// Signifies that the variant should perform recursive substituion.
//
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <typename T>
struct is_recursive_flag
: mpl::false_
{
};
template <typename T>
struct is_recursive_flag< recursive_flag<T> >
: mpl::true_
{
};
#else // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <typename T>
struct is_recursive_flag
: is_base_and_derived< recursive_flag_tag,T >
{
};
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION workaround
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction enable_recursive
//
// Attempts recursive variant substitution and wraps with boost::incomplete
// if substituion occurs *and* NoWrapper is false_.
//
template <
typename T
, typename RecursiveVariant
, typename NoWrapper = mpl::false_
>
struct enable_recursive;
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction class quoted_enable_recursive
//
// Same behavior as enable_recursive metafunction (see above).
//
template <
typename RecursiveVariant
, typename NoWrapper = mpl::false_
>
struct quoted_enable_recursive;
}} // namespace detail::variant
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_FWD_HPP

View File

@@ -1,130 +0,0 @@
//-----------------------------------------------------------------------------
// boost variant/detail/enable_recursive_stub.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_MPL_VARIANT_DETAIL_ENABLE_RECURSIVE_STUB_HPP
#define BOOST_MPL_VARIANT_DETAIL_ENABLE_RECURSIVE_STUB_HPP
#include "boost/config.hpp"
#include "boost/mpl/aux_/config/ttp.hpp"
#include "boost/incomplete_fwd.hpp"
///////////////////////////////////////////////////////////////////////////////
// (detail) macro BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT
//
// Defined if MPL lambda facility should be used as workaround for broken
// compilers.
//
#if defined(BOOST_NO_TEMPLATE_TEMPLATE_PARAMETERS) \
|| defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
&& !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
# define BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT
#endif
#if !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
# include "boost/mpl/aux_/template_arity.hpp"
# include "boost/mpl/aux_/lambda_arity_param.hpp"
# include "boost/mpl/int_fwd.hpp"
#else
# include "boost/mpl/apply.hpp"
# include "boost/mpl/apply_if.hpp"
# include "boost/mpl/identity.hpp"
# include "boost/mpl/if.hpp"
# include "boost/mpl/lambda.hpp"
# include "boost/type_traits/is_same.hpp"
#endif
namespace boost {
namespace detail { namespace variant {
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction enable_recursive
//
// Enables the boost::variant<..., boost::recursive_variant, ...> syntax.
//
#if !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
// primary template (specialized in recursive_variant.hpp)
template <
typename T, typename Variant
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(
typename Arity = mpl::int_< mpl::aux::template_arity<T>::value >
)
>
struct enable_recursive_impl
{
typedef T type;
};
#else // defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
template <typename T, typename U1>
struct rebind1
{
private:
typedef typename mpl::lambda<
mpl::identity<T>
>::type le_;
public:
typedef typename mpl::apply_if<
is_same< le_, mpl::identity<T> >
, le_ // identity<T>
, mpl::apply1<le_, U1>
>::type type;
};
template <typename T, typename Variant>
struct enable_recursive_impl
: rebind1< T,Variant >
{
};
#endif // BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT workaround
template <typename T, typename Variant>
struct enable_recursive
{
private: // helpers, for metafunction result (below)
typedef typename enable_recursive_impl<T,Variant>::type t_;
public: // metafunction result
// [Wrap with incomplete only if rebind really changed something:]
typedef typename mpl::if_<
is_same< t_,T >
, t_
, boost::incomplete<t_>
>::type type;
};
template <typename Variant>
struct quoted_enable_recursive
{
template <typename T>
struct apply
: enable_recursive<T, Variant>
{
};
};
}} // namespace detail::variant
} // namespace boost
#endif // BOOST_MPL_VARIANT_DETAIL_ENABLE_RECURSIVE_STUB_HPP

View File

@@ -0,0 +1,64 @@
//-----------------------------------------------------------------------------
// boost variant/detail/make_variant_list.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman, Itay Maman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_VARIANT_DETAIL_MAKE_VARIANT_LIST_HPP
#define BOOST_VARIANT_DETAIL_MAKE_VARIANT_LIST_HPP
#include "boost/variant/variant_fwd.hpp"
#include "boost/mpl/list.hpp"
#include "boost/preprocessor/cat.hpp"
#include "boost/preprocessor/enum.hpp"
namespace boost {
namespace detail { namespace variant {
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction make_variant_list
//
// Provides a MPL-compatible sequence with the specified non-void types
// as arguments.
//
// Rationale: see class template convert_void (variant_fwd.hpp) and using-
// declaration workaround (below).
//
template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
struct make_variant_list
{
public: // metafunction result
// [Define a macro to convert any void(NN) tags to mpl::void...]
# define BOOST_VARIANT_AUX_CONVERT_VOID(z, N,_) \
typename convert_void< BOOST_PP_CAT(T,N) >::type
// [...so that the specified types can be passed to mpl::list...]
typedef typename mpl::list<
BOOST_PP_ENUM(
BOOST_VARIANT_LIMIT_TYPES
, BOOST_VARIANT_AUX_CONVERT_VOID
, _
)
>::type type;
// [...and, finally, the conversion macro can be undefined:]
# undef BOOST_VARIANT_AUX_CONVERT_VOID
};
}} // namespace detail::variant
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_MAKE_VARIANT_LIST_HPP

View File

@@ -1,8 +1,3 @@
#if !defined(BOOST_PP_IS_ITERATING)
///// header body
//-----------------------------------------------------------------------------
// boost variant/recursive_variant.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
@@ -22,110 +17,144 @@
#ifndef BOOST_VARIANT_RECURSIVE_VARIANT_HPP
#define BOOST_VARIANT_RECURSIVE_VARIANT_HPP
#include "boost/variant/detail/enable_recursive_stub.hpp"
#include "boost/incomplete.hpp" // only forward-declared in stub header
#include "boost/variant/variant_fwd.hpp"
#include "boost/variant/detail/enable_recursive.hpp"
#include "boost/variant/detail/make_variant_list.hpp"
#include "boost/mpl/limits/arity.hpp"
#include "boost/mpl/arg.hpp"
#include "boost/mpl/aux_/lambda_arity_param.hpp"
#if !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
# include "boost/mpl/aux_/lambda_arity_param.hpp"
# include "boost/mpl/int_fwd.hpp"
# include "boost/mpl/aux_/preprocessor/params.hpp"
# include "boost/mpl/aux_/preprocessor/repeat.hpp"
# include "boost/preprocessor/arithmetic/inc.hpp"
# include "boost/preprocessor/iterate.hpp"
#if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
# include "boost/mpl/apply_if.hpp"
# include "boost/mpl/identity.hpp"
# include "boost/mpl/is_sequence.hpp"
# include "boost/mpl/protect.hpp"
# include "boost/mpl/transform.hpp"
#else
# include "boost/preprocessor/cat.hpp"
# include "boost/preprocessor/repeat.hpp"
#endif
///////////////////////////////////////////////////////////////////////////////
// (detail) macro BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY
//
// Exposes maximum allowed arity of class templates with recursive_variant
// arguments. (That is, variant< ..., T<[1], recursive_variant, ... [N]> >.)
//
#define BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY \
BOOST_MPL_METAFUNCTION_MAX_ARITY
#include "boost/mpl/bool.hpp"
#include "boost/variant/variant.hpp"
namespace boost {
///////////////////////////////////////////////////////////////////////////////
// type recursive_variant
//
// Tag type indicates where recursive variant substitution should occur.
//
typedef mpl::arg<1>
recursive_variant;
namespace detail { namespace variant {
///////////////////////////////////////////////////////////////////////////////
// (detail) class specialization template enable_recursive_impl
// (detail) metafunction specialization enable_recursive_impl
//
// Enables recursive variant substitution.
// Handles embedded variant types.
//
#if !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
namespace detail { namespace variant {
template <typename Variant>
struct enable_recursive_impl< recursive_variant, Variant >
template <
BOOST_VARIANT_ENUM_PARAMS(typename T)
, typename RecursiveVariant
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(typename Arity)
>
struct enable_recursive_impl<
::boost::variant<
recursive_flag< T0 >
, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
>
, RecursiveVariant
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(Arity)
>
{
typedef Variant type;
typedef ::boost::variant<
recursive_flag< T0 >
, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
> type;
};
#define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEF_IMPL(N) \
typedef typename enable_recursive_impl< \
BOOST_PP_CAT(U,N), Variant \
>::type BOOST_PP_CAT(u,N); \
/**/
template <
BOOST_VARIANT_ENUM_PARAMS(typename T)
, typename RecursiveVariant
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(typename Arity)
>
struct enable_recursive_impl<
::boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >
, RecursiveVariant
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(Arity)
>
{
#define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEF(z, N, _) \
BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEF_IMPL( BOOST_PP_INC(N) ) \
/**/
#if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
#define BOOST_PP_ITERATION_LIMITS (1,BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY)
#define BOOST_PP_FILENAME_1 "boost/variant/recursive_variant.hpp"
#include BOOST_PP_ITERATE()
private: // helpers, for metafunction result (below)
#undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEF_IMPL
#undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEF
typedef typename mpl::apply_if<
mpl::is_sequence<T0>
, mpl::identity< T0 >
, make_variant_list< BOOST_VARIANT_ENUM_PARAMS(T) >
>::type initial_types;
}} // namespace detail::variant
typedef typename mpl::transform<
initial_types
, mpl::protect< quoted_enable_recursive<RecursiveVariant,mpl::true_> >
>::type types;
public: // metafunction result
typedef ::boost::variant< types > type;
#else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
private: // helpers, for metafunction result (below)
#define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
typedef typename enable_recursive< \
BOOST_PP_CAT(T,N) \
, RecursiveVariant \
, mpl::true_ \
>::type BOOST_PP_CAT(wknd_T,N); \
/**/
BOOST_PP_REPEAT(
BOOST_VARIANT_LIMIT_TYPES
, BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
, _
)
#undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
public: // metafunction result
typedef ::boost::variant< BOOST_VARIANT_ENUM_PARAMS(wknd_T) > type;
#endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround
};
#else // defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
//
// see detail/enable_recursive_stub.hpp for workaround.
// no specializations: embedded variants unsupported on these compilers!
//
#endif // !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
}} // namespace detail::variant
///////////////////////////////////////////////////////////////////////////////
// metafunction recursive_variant
//
// See docs and boost/variant/variant_fwd.hpp for more information.
//
template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
struct recursive_variant
{
public: // metafunction result
typedef boost::variant<
detail::variant::recursive_flag< T0 >
, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
> type;
};
} // namespace boost
#endif // BOOST_VARIANT_RECURSIVE_VARIANT_HPP
///// iteration, depth == 1
#elif BOOST_PP_ITERATION_DEPTH() == 1
#define i BOOST_PP_FRAME_ITERATION(1)
template <
template < BOOST_MPL_PP_PARAMS(i,typename P) > class T
, BOOST_MPL_PP_PARAMS(i,typename U)
, typename Variant
>
struct enable_recursive_impl<
T< BOOST_MPL_PP_PARAMS(i,U) >
, Variant
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<( i )>)
>
{
private:
BOOST_MPL_PP_REPEAT(i, BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEF, _)
public:
typedef T< BOOST_MPL_PP_PARAMS(i,u) > type;
};
#undef i
#endif // BOOST_PP_IS_ITERATING

View File

@@ -22,8 +22,9 @@
#include <typeinfo> // for typeid, std::type_info
#include "boost/variant/variant_fwd.hpp"
#include "boost/variant/detail/enable_recursive_fwd.hpp"
#include "boost/variant/detail/make_variant_list.hpp"
#include "boost/variant/detail/visitation_impl.hpp"
#include "boost/variant/detail/enable_recursive_stub.hpp"
#include "boost/variant/detail/generic_result_type.hpp"
#include "boost/variant/detail/has_nothrow_move.hpp"
@@ -60,12 +61,11 @@
#include "boost/mpl/int.hpp"
#include "boost/mpl/is_sequence.hpp"
#include "boost/mpl/iter_fold.hpp"
#include "boost/mpl/front.hpp"
#include "boost/mpl/list.hpp"
#include "boost/mpl/logical.hpp"
#include "boost/mpl/max_element.hpp"
#include "boost/mpl/next.hpp"
#include "boost/mpl/pair.hpp"
#include "boost/mpl/protect.hpp"
#include "boost/mpl/remove_if.hpp"
#include "boost/mpl/sizeof.hpp"
#include "boost/mpl/size_t.hpp"
@@ -93,6 +93,7 @@
# include "boost/mpl/O1_size.hpp"
#endif
namespace boost {
namespace detail { namespace variant {
@@ -491,40 +492,6 @@ public: // visitor interfaces
};
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction make_variant_list
//
// Provides a MPL-compatible sequence with the specified non-void types
// as arguments.
//
// Rationale: see class template convert_void (variant_fwd.hpp) and using-
// declaration workaround (below).
//
template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
struct make_variant_list
{
public: // metafunction result
// [Define a macro to convert any void(NN) tags to mpl::void...]
# define BOOST_VARIANT_AUX_CONVERT_VOID(z, N,_) \
typename convert_void<BOOST_PP_CAT(T,N)>::type
// [...so that the specified types can be passed to mpl::list...]
typedef typename mpl::list<
BOOST_PP_ENUM(
BOOST_VARIANT_LIMIT_TYPES
, BOOST_VARIANT_AUX_CONVERT_VOID
, _
)
>::type type;
// [...and, finally, the conversion macro can be undefined:]
# undef BOOST_VARIANT_AUX_CONVERT_VOID
};
#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
///////////////////////////////////////////////////////////////////////////////
// (detail) support for MPL-Sequence initializer
//
@@ -532,6 +499,8 @@ public: // metafunction result
// overload resolution rules on any specified set of bounded types.
//
#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
// (detail) quoted metafunction make_initializer_node
//
// Exposes a pair whose first type is a node in the initializer hierarchy.
@@ -593,6 +562,13 @@ public: // static functions
};
#else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
//
// MPL-sequence initializer cannot be supported on these compilers.
// See preprocessor_list_initializer workaround below.
//
#endif // !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
}} // namespace detail::variant
@@ -603,57 +579,76 @@ public: // static functions
// See docs and boost/variant/variant_fwd.hpp for more information.
//
template <
BOOST_VARIANT_ENUM_PARAMS(typename T_)
>
typename T0_
#if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
#elif !BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename wknd_T)
#else // MSVC6
, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
#endif
>
class variant
{
private: // private typedefs
struct is_recursive
: detail::variant::is_recursive_flag<T0_>
{
};
#if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
private: // helpers, for typedefs (below)
typedef typename mpl::apply_if<
mpl::is_sequence<T_0>
, mpl::identity<T_0>
is_recursive
, T0_
, mpl::identity< T0_ >
>::type T0;
typedef typename mpl::apply_if<
mpl::is_sequence<T0>
, mpl::identity<T0>
, detail::variant::make_variant_list<
BOOST_VARIANT_ENUM_PARAMS(T_)
BOOST_VARIANT_ENUM_PARAMS(T)
>
>::type plain_nonrecursive_types;
>::type initial_types;
public: // typedefs
typedef typename mpl::transform<
plain_nonrecursive_types
, mpl::protect< detail::variant::quoted_enable_recursive<variant> >
typedef typename mpl::apply_if<
is_recursive
, mpl::transform<
initial_types
, mpl::protect<
detail::variant::quoted_enable_recursive<variant>
>
>
, mpl::identity< initial_types >
>::type types;
private: // private typedefs
typedef typename mpl::front<types>::type T0;
#else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
#elif !BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
private: // helpers, for typedefs (below)
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
typedef typename mpl::apply_if<
is_recursive
, T0_
, mpl::identity< T0_ >
>::type wknd_T0;
typedef variant wknd_self_t;
#define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
typedef typename detail::variant::enable_recursive< \
BOOST_PP_CAT(T_,N) \
, wknd_self_t \
>::type BOOST_PP_CAT(T,N); \
#define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
typedef typename mpl::apply_if< \
is_recursive \
, detail::variant::enable_recursive< \
BOOST_PP_CAT(wknd_T,N) \
, variant \
> \
, mpl::identity< BOOST_PP_CAT(wknd_T,N) > \
>::type BOOST_PP_CAT(T,N); \
/**/
# else // MSVC7 and below
#define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
typedef BOOST_PP_CAT(T_,N) BOOST_PP_CAT(T,N); \
/**/
# endif // MSVC7 and below workaround
BOOST_PP_REPEAT(
BOOST_VARIANT_LIMIT_TYPES
, BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
@@ -670,24 +665,40 @@ public: // typedefs
private: // static precondition assertions
// Sequences are not supported for compilers that do not support
// using declarations in templates (see below).
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
// NOTE TO USER :
// variant< type-sequence > syntax is not supported on this compiler!
//
BOOST_STATIC_ASSERT((
::boost::mpl::not_< mpl::is_sequence<T0> >::value
));
# else // MSVC6
#else // MSVC6
public: // typedefs
typedef T0_ T0;
typedef typename detail::variant::make_variant_list<
BOOST_VARIANT_ENUM_PARAMS(T)
>::type types;
private: // static precondition assertions
// for some reason, msvc needs following all on one line:
BOOST_STATIC_CONSTANT(bool, msvc_not_is_sequence_T0 = mpl::not_< mpl::is_sequence<T0> >::value);
BOOST_STATIC_CONSTANT(bool, msvc_not_is_recursive = mpl::not_< is_recursive >::value);
BOOST_STATIC_CONSTANT(bool, msvc_not_is_sequence_T0 = mpl::not_< mpl::is_sequence<T0_> >::value);
// NOTE TO USER :
// recursive_variant is not supported on MSVC6!
//
BOOST_STATIC_ASSERT(msvc_not_is_recursive);
// NOTE TO USER :
// variant< type-sequence > syntax is not supported on MSVC6!
//
BOOST_STATIC_ASSERT(msvc_not_is_sequence_T0);
# endif // MSVC6 workaround
#endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT
#endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT and MSVC6 workaround
private: // static precondition assertions, cont.

View File

@@ -18,32 +18,27 @@
#define BOOST_VARIANT_VARIANT_FWD_HPP
#include "boost/config.hpp"
#include "boost/mpl/limits/list.hpp"
#include "boost/empty_fwd.hpp"
#include "boost/mpl/arg.hpp"
#include "boost/mpl/void.hpp"
#include "boost/preprocessor/cat.hpp"
#include "boost/preprocessor/dec.hpp"
#include "boost/preprocessor/enum_params.hpp"
#include "boost/preprocessor/enum_shifted.hpp"
#include "boost/preprocessor/enum_shifted_params.hpp"
#include "boost/preprocessor/repeat.hpp"
#include "boost/empty_fwd.hpp"
#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
# include "boost/preprocessor/enum_params_with_a_default.hpp"
#else
# include "boost/preprocessor/enum_params_with_defaults.hpp"
#endif
///////////////////////////////////////////////////////////////////////////////
// macro BOOST_VARIANT_LIMIT_TYPES
//
// Implementation-defined preprocessor symbol describing the actual
// length of variant's pseudo-variadic template parameter list.
//
#include "boost/mpl/limits/list.hpp"
#define BOOST_VARIANT_LIMIT_TYPES \
BOOST_MPL_LIMIT_LIST_SIZE
///////////////////////////////////////////////////////////////////////////////
// BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT
// macro BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT
//
// Defined if variant does not support variant<Types> syntax (see below).
//
@@ -51,6 +46,32 @@
# define BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT
#endif
///////////////////////////////////////////////////////////////////////////////
// macro BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT
//
// Defined if MPL lambda facility should be used as workaround for broken
// compilers. (Thus, only types w/ MPL lambda workarounds can be accepted.)
//
#include "boost/mpl/aux_/config/ctps.hpp"
#include "boost/mpl/aux_/config/ttp.hpp"
#if defined(BOOST_NO_TEMPLATE_TEMPLATE_PARAMETERS) \
|| defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
&& !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
# define BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT
#endif
///////////////////////////////////////////////////////////////////////////////
// macro BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY
//
// Exposes maximum allowed arity of class templates with recursive_variant
// arguments. (That is, variant< ..., T<[1], recursive_variant, ... [N]> >.)
//
#include "boost/mpl/limits/arity.hpp"
#define BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY \
BOOST_MPL_METAFUNCTION_MAX_ARITY
///////////////////////////////////////////////////////////////////////////////
// macro BOOST_VARIANT_ENUM_PARAMS
//
@@ -61,6 +82,14 @@
#define BOOST_VARIANT_ENUM_PARAMS( param ) \
BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, param)
///////////////////////////////////////////////////////////////////////////////
// macro BOOST_VARIANT_ENUM_SHIFTED_PARAMS
//
// Convenience macro for enumeration of BOOST_VARIANT_LIMIT_TYPES-1 params.
//
#define BOOST_VARIANT_ENUM_SHIFTED_PARAMS( param ) \
BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_VARIANT_LIMIT_TYPES, param)
namespace boost {
@@ -101,7 +130,7 @@ struct convert_void< void_ >
#if defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
// (detail) tags voidNN -- NN defined on [0, BOOST_VARIANT_LIMIT_TYPES - 1)
// (detail) tags voidNN -- NN defined on [0, BOOST_VARIANT_LIMIT_TYPES)
//
// Defines void types that are each unique and specializations of
// convert_void that yields mpl::void_ for each voidNN type.
@@ -118,7 +147,7 @@ struct convert_void< void_ >
/**/
BOOST_PP_REPEAT(
BOOST_PP_DEC(BOOST_VARIANT_LIMIT_TYPES)
BOOST_VARIANT_LIMIT_TYPES
, BOOST_VARIANT_DETAIL_DEFINE_VOID_N
, _
)
@@ -129,6 +158,35 @@ BOOST_PP_REPEAT(
}} // namespace detail::variant
///////////////////////////////////////////////////////////////////////////////
// (detail) macro BOOST_VARIANT_AUX_DECLARE_PARAM
//
// Template parameter list for variant and recursive_variant declarations.
//
#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
# define BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL(z, N, T) \
typename BOOST_PP_CAT(T,N) = detail::variant::void_ \
/**/
#else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
# define BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL(z, N, T) \
typename BOOST_PP_CAT(T,N) = BOOST_PP_CAT(detail::variant::void,N) \
/**/
#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround
#define BOOST_VARIANT_AUX_DECLARE_PARAMS \
typename T0 = boost::empty \
, BOOST_PP_ENUM_SHIFTED( \
BOOST_VARIANT_LIMIT_TYPES \
, BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL \
, T \
) \
/**/
///////////////////////////////////////////////////////////////////////////////
// class template variant (concept inspired by Andrei Alexandrescu)
//
@@ -145,30 +203,29 @@ BOOST_PP_REPEAT(
// or
// variant<>, which is variant<boost::empty>
//
template <
template < BOOST_VARIANT_AUX_DECLARE_PARAMS > class variant;
typename First = boost::empty,
///////////////////////////////////////////////////////////////////////////////
// metafunction recursive_variant
//
// Exposes a boost::variant with recursive_variant_ tags (below) substituted
// with the variant itself (wrapped as needed with boost::incomplete).
//
template < BOOST_VARIANT_AUX_DECLARE_PARAMS > struct recursive_variant;
#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
#undef BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL
#undef BOOST_VARIANT_AUX_DECLARE_PARAMS
BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
BOOST_PP_DEC(BOOST_VARIANT_LIMIT_TYPES)
, typename T
, detail::variant::void_
)
#else// defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
BOOST_PP_ENUM_PARAMS_WITH_DEFAULTS(
BOOST_PP_DEC(BOOST_VARIANT_LIMIT_TYPES)
, typename T
, detail::variant::void//NN
)
#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround
>
class variant;
///////////////////////////////////////////////////////////////////////////////
// type recursive_variant_
//
// Tag type indicates where recursive variant substitution should occur.
//
#if !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
struct recursive_variant_;
#else
typedef mpl::arg<1> recursive_variant_;
#endif
} // namespace boost