Edit: /usr/include/boost/proto/matches.hpp (34801B)
///////////////////////////////////////////////////////////////////////////////
/// \file matches.hpp
/// Contains definition of matches\<\> metafunction for determining if
/// a given expression matches a given pattern.
//
// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROTO_MATCHES_HPP_EAN_11_03_2006
#define BOOST_PROTO_MATCHES_HPP_EAN_11_03_2006
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
#include
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable:4305) // 'specialization' : truncation from 'const int' to 'bool'
#endif
#define BOOST_PROTO_LOGICAL_typename_G BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_LOGICAL_ARITY, typename G)
#define BOOST_PROTO_LOGICAL_G BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_LOGICAL_ARITY, G)
namespace boost { namespace proto
{
namespace detail
{
template
struct matches_;
template
struct and_2;
template
struct _and_impl;
template
struct array_matches
: mpl::false_
{};
template
struct array_matches
: mpl::true_
{};
template
struct array_matches
: mpl::true_
{};
template
struct array_matches
: mpl::true_
{};
template::value)
>
struct lambda_matches
: mpl::false_
{};
template
struct lambda_matches
: mpl::true_
{};
template
struct lambda_matches
: mpl::true_
{};
template
struct lambda_matches
: array_matches
{};
template
struct lambda_matches
: mpl::true_
{};
template
struct lambda_matches
: mpl::true_
{};
template class T, typename Expr0, typename Grammar0>
struct lambda_matches, T BOOST_PROTO_TEMPLATE_ARITY_PARAM(1) >
: lambda_matches
{};
// vararg_matches_impl
template
struct vararg_matches_impl;
// vararg_matches
template
struct vararg_matches
: mpl::false_
{};
template
struct vararg_matches
: matches_<
Expr
, proto::basic_expr
, proto::basic_expr
>
{};
template
struct vararg_matches
: and_2<
matches_<
Expr
, proto::basic_expr
, proto::basic_expr
>::value
, vararg_matches_impl
>
{};
// How terminal_matches<> handles references and cv-qualifiers.
// The cv and ref matter *only* if the grammar has a top-level ref.
//
// Expr | Grammar | Matches?
// -------------------------------------
// T T yes
// T & T yes
// T const & T yes
// T T & no
// T & T & yes
// T const & T & no
// T T const & no
// T & T const & no
// T const & T const & yes
template
struct is_cv_ref_compatible
: mpl::true_
{};
template
struct is_cv_ref_compatible
: mpl::false_
{};
template
struct is_cv_ref_compatible
: mpl::bool_::value == is_const::value>
{};
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
// MSVC-7.1 has lots of problems with array types that have been
// deduced. Partially specializing terminal_matches<> on array types
// doesn't seem to work.
template<
typename T
, typename U
, bool B = is_array::value
>
struct terminal_array_matches
: mpl::false_
{};
template
struct terminal_array_matches
: is_convertible
{};
template
struct terminal_array_matches
: is_convertible
{};
template
struct terminal_array_matches
: is_convertible
{};
// terminal_matches
template
struct terminal_matches
: mpl::or_<
mpl::and_<
is_cv_ref_compatible
, lambda_matches<
BOOST_PROTO_UNCVREF(T)
, BOOST_PROTO_UNCVREF(U)
>
>
, terminal_array_matches
>
{};
#else
// terminal_matches
template
struct terminal_matches
: mpl::and_<
is_cv_ref_compatible
, lambda_matches<
BOOST_PROTO_UNCVREF(T)
, BOOST_PROTO_UNCVREF(U)
>
>
{};
template
struct terminal_matches
: mpl::true_
{};
template
struct terminal_matches
: mpl::true_
{};
// Avoid ambiguity errors on MSVC
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
template
struct terminal_matches
: mpl::true_
{};
#endif
#endif
template
struct terminal_matches
: mpl::true_
{};
template
struct terminal_matches
: mpl::true_
{};
template
struct terminal_matches
: mpl::true_
{};
template
struct terminal_matches
: mpl::true_
{};
template
struct terminal_matches >
: mpl::true_
{};
template
struct terminal_matches >
: is_convertible
{};
// matches_
template
struct matches_
: mpl::false_
{};
template
struct matches_< Expr, BasicExpr, proto::_ >
: mpl::true_
{};
template
struct matches_< Expr, proto::basic_expr, proto::basic_expr >
: vararg_matches< Expr, Args1, Args2, typename Args2::back_, (N1+2 > N2), (N2 > N1) >
{};
template
struct matches_< Expr, proto::basic_expr, proto::basic_expr >
: vararg_matches< Expr, Args1, Args2, typename Args2::back_, (N1+2 > N2), (N2 > N1) >
{};
template
struct matches_< Expr, proto::basic_expr, proto::basic_expr >
: terminal_matches
{};
template
struct matches_< Expr, proto::basic_expr, proto::basic_expr >
: mpl::false_
{};
template
struct matches_< Expr, proto::basic_expr, proto::basic_expr >
: terminal_matches
{};
template
struct matches_< Expr, proto::basic_expr, proto::basic_expr >
: matches_<
typename detail::expr_traits::value_type::proto_derived_expr
, typename detail::expr_traits::value_type::proto_grammar
, typename Args2::child0::proto_grammar
>
{};
template
struct matches_< Expr, proto::basic_expr, proto::basic_expr >
: matches_<
typename detail::expr_traits::value_type::proto_derived_expr
, typename detail::expr_traits::value_type::proto_grammar
, typename Args2::child0::proto_grammar
>
{};
#include
#include
#include
#include
#include
// handle proto::if_
template
struct matches_, proto::if_ >
: mpl::eval_if_c<
static_cast(
remove_reference<
typename when<_, If>::template impl::result_type
>::type::value
)
, matches_, typename Then::proto_grammar>
, matches_, typename Else::proto_grammar>
>::type
{
typedef
typename mpl::if_c<
static_cast(
remove_reference<
typename when<_, If>::template impl::result_type
>::type::value
)
, Then
, Else
>::type
which;
};
// handle degenerate cases of proto::or_
template
struct matches_ >
: mpl::false_
{
typedef not_<_> which;
};
template
struct matches_ >
: matches_
{
typedef G0 which;
};
// handle degenerate cases of proto::and_
template
struct matches_ >
: mpl::true_
{};
template
struct matches_ >
: matches_
{};
// handle proto::not_
template
struct matches_ >
: mpl::not_ >
{};
// handle proto::switch_
template
struct matches_, switch_ >
: matches_<
Expr
, proto::basic_expr
, typename Cases::template case_<
typename when<_,Transform>::template impl::result_type
>::proto_grammar
>
{
typedef
typename Cases::template case_<
typename when<_, Transform>::template impl::result_type
>
which;
};
// handle proto::switch_ with the default Transform for specially for better compile times
template
struct matches_, switch_ >
: matches_<
Expr
, proto::basic_expr
, typename Cases::template case_::proto_grammar
>
{
typedef typename Cases::template case_ which;
};
}
/// \brief A Boolean metafunction that evaluates whether a given
/// expression type matches a grammar.
///
/// matches\ inherits (indirectly) from
/// \c mpl::true_ if Expr::proto_grammar matches
/// Grammar::proto_grammar, and from \c mpl::false_
/// otherwise.
///
/// Non-terminal expressions are matched against a grammar
/// according to the following rules:
///
/// \li The wildcard pattern, \c _, matches any expression.
/// \li An expression expr\ \>
/// matches a grammar expr\ \>
/// if \c BT is \c _ or \c AT, and if \c Ax matches \c Bx for
/// each \c x in [0,n).
/// \li An expression expr\ \>
/// matches a grammar expr\ \> \>
/// if \c BT is \c _ or \c AT, and if \c Ax matches \c Bx
/// for each \c x in [0,n) and if \c Ux matches \c V
/// for each \c x in [0,m).
/// \li An expression \c E matches or_\ if \c E
/// matches some \c Bx for \c x in [0,n).
/// \li An expression \c E matches and_\ if \c E
/// matches all \c Bx for \c x in [0,n).
/// \li An expression \c E matches if_\ if
/// boost::result_of\(E,int,int)\>::type::value
/// is \c true and \c E matches \c U; or, if
/// boost::result_of\(E,int,int)\>::type::value
/// is \c false and \c E matches \c V. (Note: \c U defaults to \c _
/// and \c V defaults to \c not_\<_\>.)
/// \li An expression \c E matches not_\ if \c E does
/// not match \c T.
/// \li An expression \c E matches switch_\ if
/// \c E matches C::case_\::type\>.
/// (Note: T defaults to tag_of\<_\>().)
///
/// A terminal expression expr\ \> matches
/// a grammar expr\ \> if \c BT is \c AT or
/// \c proto::_ and if one of the following is true:
///
/// \li \c B is the wildcard pattern, \c _
/// \li \c A is \c B
/// \li \c A is B &
/// \li \c A is B const &
/// \li \c B is exact\
/// \li \c B is convertible_to\ and
/// is_convertible\::value is \c true.
/// \li \c A is X[M] or X(&)[M] and
/// \c B is X[proto::N].
/// \li \c A is X(&)[M] and \c B is X(&)[proto::N].
/// \li \c A is X[M] or X(&)[M] and
/// \c B is X*.
/// \li \c B lambda-matches \c A (see below).
///
/// A type \c B lambda-matches \c A if one of the following is true:
///
/// \li \c B is \c A
/// \li \c B is the wildcard pattern, \c _
/// \li \c B is T\ and \c A is
/// T\ and for each \c x in
/// [0,n), \c Ax and \c Bx are types
/// such that \c Ax lambda-matches \c Bx
template
struct matches
: detail::matches_<
typename Expr::proto_derived_expr
, typename Expr::proto_grammar
, typename Grammar::proto_grammar
>
{};
/// INTERNAL ONLY
///
template
struct matches
: detail::matches_<
typename Expr::proto_derived_expr
, typename Expr::proto_grammar
, typename Grammar::proto_grammar
>
{};
/// \brief A wildcard grammar element that matches any expression,
/// and a transform that returns the current expression unchanged.
///
/// The wildcard type, \c _, is a grammar element such that
/// matches\::value is \c true for any expression
/// type \c E.
///
/// The wildcard can also be used as a stand-in for a template
/// argument when matching terminals. For instance, the following
/// is a grammar that will match any std::complex\<\>
/// terminal:
///
/// \code
/// BOOST_MPL_ASSERT((
/// matches<
/// terminal >::type
/// , terminal >
/// >
/// ));
/// \endcode
///
/// When used as a transform, \c _ returns the current expression
/// unchanged. For instance, in the following, \c _ is used with
/// the \c fold\<\> transform to fold the children of a node:
///
/// \code
/// struct CountChildren
/// : or_<
/// // Terminals have no children
/// when, mpl::int_<0>()>
/// // Use fold<> to count the children of non-terminals
/// , otherwise<
/// fold<
/// _ // <-- fold the current expression
/// , mpl::int_<0>()
/// , mpl::plus<_state, mpl::int_<1> >()
/// >
/// >
/// >
/// {};
/// \endcode
struct _ : transform<_>
{
typedef _ proto_grammar;
template
struct impl : transform_impl
{
typedef Expr result_type;
/// \param expr An expression
/// \return \c e
BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::expr_param)
operator()(
typename impl::expr_param e
, typename impl::state_param
, typename impl::data_param
) const
{
return e;
}
};
};
namespace detail
{
template
struct _and_impl, Expr, State, Data>
: proto::_::impl
{};
template
struct _and_impl, Expr, State, Data>
: proto::when::template impl
{};
}
/// \brief Inverts the set of expressions matched by a grammar. When
/// used as a transform, \c not_\<\> returns the current expression
/// unchanged.
///
/// If an expression type \c E does not match a grammar \c G, then
/// \c E \e does match not_\. For example,
/// not_\ \> will match any non-terminal.
template
struct not_ : transform >
{
typedef not_ proto_grammar;
template
struct impl : transform_impl
{
typedef Expr result_type;
/// \param e An expression
/// \pre matches\::value is \c true.
/// \return \c e
BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::expr_param)
operator()(
typename impl::expr_param e
, typename impl::state_param
, typename impl::data_param
) const
{
return e;
}
};
};
/// \brief Used to select one grammar or another based on the result
/// of a compile-time Boolean. When used as a transform, \c if_\<\>
/// selects between two transforms based on a compile-time Boolean.
///
/// When if_\ is used as a grammar, \c If
/// must be a Proto transform and \c Then and \c Else must be grammars.
/// An expression type \c E matches if_\ if
/// boost::result_of\(E,int,int)\>::type::value
/// is \c true and \c E matches \c U; or, if
/// boost::result_of\(E,int,int)\>::type::value
/// is \c false and \c E matches \c V.
///
/// The template parameter \c Then defaults to \c _
/// and \c Else defaults to \c not\<_\>, so an expression type \c E
/// will match if_\ if and only if
/// boost::result_of\(E,int,int)\>::type::value
/// is \c true.
///
/// \code
/// // A grammar that only matches integral terminals,
/// // using is_integral<> from Boost.Type_traits.
/// struct IsIntegral
/// : and_<
/// terminal<_>
/// , if_< is_integral<_value>() >
/// >
/// {};
/// \endcode
///
/// When if_\ is used as a transform, \c If,
/// \c Then and \c Else must be Proto transforms. When applying
/// the transform to an expression \c E, state \c S and data \c V,
/// if boost::result_of\(E,S,V)\>::type::value
/// is \c true then the \c Then transform is applied; otherwise
/// the \c Else transform is applied.
///
/// \code
/// // Match a terminal. If the terminal is integral, return
/// // mpl::true_; otherwise, return mpl::false_.
/// struct IsIntegral2
/// : when<
/// terminal<_>
/// , if_<
/// is_integral<_value>()
/// , mpl::true_()
/// , mpl::false_()
/// >
/// >
/// {};
/// \endcode
template<
typename If
, typename Then // = _
, typename Else // = not_<_>
>
struct if_ : transform >
{
typedef if_ proto_grammar;
template
struct impl : transform_impl
{
typedef
typename when<_, If>::template impl::result_type
condition;
typedef
typename mpl::if_c<
static_cast(remove_reference::type::value)
, when<_, Then>
, when<_, Else>
>::type
which;
typedef typename which::template impl::result_type result_type;
/// \param e An expression
/// \param s The current state
/// \param d A data of arbitrary type
/// \return which::impl()(e, s, d)
result_type operator ()(
typename impl::expr_param e
, typename impl::state_param s
, typename impl::data_param d
) const
{
return typename which::template impl()(e, s, d);
}
};
};
/// \brief For matching one of a set of alternate grammars. Alternates
/// tried in order to avoid ambiguity. When used as a transform, \c or_\<\>
/// applies the transform associated with the first grammar that matches
/// the expression.
///
/// An expression type \c E matches or_\ if \c E
/// matches any \c Bx for \c x in [0,n).
///
/// When applying or_\ as a transform with an
/// expression \c e of type \c E, state \c s and data \c d, it is
/// equivalent to Bx()(e, s, d), where \c x is the lowest
/// number such that matches\::value is \c true.
template
struct or_ : transform >
{
typedef or_ proto_grammar;
/// \param e An expression
/// \param s The current state
/// \param d A data of arbitrary type
/// \pre matches\::value is \c true.
/// \return which()(e, s, d), where which is the
/// sub-grammar that matched Expr.
template
struct impl
: detail::matches_<
typename Expr::proto_derived_expr
, typename Expr::proto_grammar
, or_
>::which::template impl
{};
template
struct impl
: detail::matches_<
typename Expr::proto_derived_expr
, typename Expr::proto_grammar
, or_
>::which::template impl
{};
};
/// \brief For matching all of a set of grammars. When used as a
/// transform, \c and_\<\> applies the transforms associated with
/// the each grammar in the set, and returns the result of the last.
///
/// An expression type \c E matches and_\ if \c E
/// matches all \c Bx for \c x in [0,n).
///
/// When applying and_\ as a transform with an
/// expression \c e, state \c s and data \c d, it is
/// equivalent to (B0()(e, s, d),B1()(e, s, d),...Bn()(e, s, d)).
template
struct and_ : transform >
{
typedef and_ proto_grammar;
template
struct impl
: detail::_and_impl
{};
};
/// \brief For matching one of a set of alternate grammars, which
/// are looked up based on some property of an expression. The
/// property on which to dispatch is specified by the \c Transform
/// template parameter, which defaults to tag_of\<_\>().
/// That is, when the \c Trannsform is not specified, the alternate
/// grammar is looked up using the tag type of the current expression.
///
/// When used as a transform, \c switch_\<\> applies the transform
/// associated with the grammar that matches the expression.
///
/// \note \c switch_\<\> is functionally identical to \c or_\<\> but
/// is often more efficient. It does a fast, O(1) lookup using the
/// result of the specified transform to find a sub-grammar that may
/// potentially match the expression.
///
/// An expression type \c E matches switch_\ if \c E
/// matches C::case_\::type\>.
///
/// When applying switch_\ as a transform with an
/// expression \c e of type \c E, state \c s of type \S and data
/// \c d of type \c D, it is equivalent to
/// C::case_\::type\>()(e, s, d).
template
struct switch_ : transform >
{
typedef switch_ proto_grammar;
template
struct impl
: Cases::template case_<
typename when<_, Transform>::template impl::result_type
>::template impl
{};
};
/// INTERNAL ONLY (This is merely a compile-time optimization for the common case)
///
template
struct switch_ : transform >
{
typedef switch_ proto_grammar;
template
struct impl
: Cases::template case_::template impl
{};
template
struct impl
: Cases::template case_::template impl
{};
};
/// \brief For forcing exact matches of terminal types.
///
/// By default, matching terminals ignores references and
/// cv-qualifiers. For instance, a terminal expression of
/// type terminal\::type will match
/// the grammar terminal\. If that is not
/// desired, you can force an exact match with
/// terminal\ \>. This will only
/// match integer terminals where the terminal is held by
/// value.
template
struct exact
{};
/// \brief For matching terminals that are convertible to
/// a type.
///
/// Use \c convertible_to\<\> to match a terminal that is
/// convertible to some type. For example, the grammar
/// terminal\ \> will match
/// any terminal whose argument is convertible to an integer.
///
/// \note The trait \c is_convertible\<\> from Boost.Type_traits
/// is used to determinal convertibility.
template
struct convertible_to
{};
/// \brief For matching a Grammar to a variable number of
/// sub-expressions.
///
/// An expression type expr\ \>
/// matches a grammar expr\ \> \>
/// if \c BT is \c _ or \c AT, and if \c Ax matches \c Bx
/// for each \c x in [0,n) and if \c Ux matches \c V
/// for each \c x in [0,m).
///
/// For example:
///
/// \code
/// // Match any function call expression, irregardless
/// // of the number of function arguments:
/// struct Function
/// : function< vararg<_> >
/// {};
/// \endcode
///
/// When used as a transform, vararg\ applies
/// G's transform.
template
struct vararg
: Grammar
{
/// INTERNAL ONLY
typedef void proto_is_vararg_;
};
/// INTERNAL ONLY
///
template
struct is_callable >
: mpl::true_
{};
/// INTERNAL ONLY
///
template
struct is_callable >
: mpl::true_
{};
/// INTERNAL ONLY
///
template
struct is_callable >
: mpl::true_
{};
/// INTERNAL ONLY
///
template
struct is_callable >
: mpl::true_
{};
/// INTERNAL ONLY
///
template
struct is_callable >
: mpl::true_
{};
/// INTERNAL ONLY
///
template
struct is_callable >
: mpl::true_
{};
}}
#undef BOOST_PROTO_LOGICAL_typename_G
#undef BOOST_PROTO_LOGICAL_G
#if defined(_MSC_VER)
# pragma warning(pop)
#endif
#endif