|
Boost-Commit : |
From: eric_at_[hidden]
Date: 2008-02-21 02:18:25
Author: eric_niebler
Date: 2008-02-21 02:18:24 EST (Thu, 21 Feb 2008)
New Revision: 43344
URL: http://svn.boost.org/trac/boost/changeset/43344
Log:
More Proto documentation
Text files modified:
trunk/boost/xpressive/proto/proto.hpp | 3
trunk/boost/xpressive/proto/ref.hpp | 135 ++++++++++++++++++++-----
trunk/boost/xpressive/proto/transform/bind.hpp | 44 +++++++-
trunk/boost/xpressive/proto/transform/call.hpp | 204 +++++++++++++++++++++++++++++++++------
trunk/boost/xpressive/proto/transform/fold.hpp | 38 ++++++
trunk/boost/xpressive/proto/transform/fold_tree.hpp | 134 ++++++++++++++++++++-----
trunk/boost/xpressive/proto/transform/make.hpp | 61 ++++++++++-
trunk/libs/xpressive/proto/doc/examples.qbk | 109 ++++++++++++--------
trunk/libs/xpressive/proto/doc/implementation.qbk | 160 +++++++++++++++++++++++++++++++
trunk/libs/xpressive/proto/doc/proto.qbk | 3
10 files changed, 733 insertions(+), 158 deletions(-)
Modified: trunk/boost/xpressive/proto/proto.hpp
==============================================================================
--- trunk/boost/xpressive/proto/proto.hpp (original)
+++ trunk/boost/xpressive/proto/proto.hpp 2008-02-21 02:18:24 EST (Thu, 21 Feb 2008)
@@ -1,6 +1,7 @@
///////////////////////////////////////////////////////////////////////////////
/// \file proto.hpp
-/// The proto expression template compiler and supporting utilities.
+/// Includes the core of Proto. Not included are the contexts, transforms and
+/// debugging utilities.
//
// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
Modified: trunk/boost/xpressive/proto/ref.hpp
==============================================================================
--- trunk/boost/xpressive/proto/ref.hpp (original)
+++ trunk/boost/xpressive/proto/ref.hpp 2008-02-21 02:18:24 EST (Thu, 21 Feb 2008)
@@ -27,14 +27,24 @@
namespace boost { namespace proto
{
-#define BOOST_PROTO_ARG(z, n, data)\
- typedef\
- typename Expr::BOOST_PP_CAT(proto_arg, n)\
- BOOST_PP_CAT(proto_arg, n);\
+#define BOOST_PROTO_ARG(z, n, data) \
+ typedef \
+ typename Expr::BOOST_PP_CAT(proto_arg, n) \
+ BOOST_PP_CAT(proto_arg, n); \
/**/
namespace refns_
{
+ /// \brief A simple reference wrapper for a Proto expression type,
+ /// used by <tt>expr\<\></tt> to hold children expressions by reference.
+ ///
+ /// <tt>ref_\<\></tt> is used by <tt>expr\<\></tt> to hold children
+ /// expression types by reference. It forwards enough of the child
+ /// expression's interface so that <tt>expr\<\></tt> can handle children
+ /// uniformly regardless of whether it is stored by reference or by
+ /// value.
+ ///
+ /// This type is largely an implementation detail.
template<typename Expr>
struct ref_
{
@@ -65,6 +75,7 @@
};
// ref_-to-ref_ is not allowed. this will cause a compile error.
+ /// INTERNAL ONLY
template<typename Expr>
struct ref_<ref_<Expr> >
{};
@@ -74,93 +85,125 @@
namespace result_of
{
+ /// \brief Trait for stripping top-level references
+ /// and reference wrappers.
template<typename T>
struct unref
{
- typedef T type;
- typedef T &reference;
- typedef T const &const_reference;
+ typedef T type; ///< Suitable for return by value
+ typedef T &reference; ///< Suitable for return by reference
+ typedef T const &const_reference; ///< Suitable for return by const reference
};
+ /// \brief Trait for stripping top-level references
+ /// and reference wrappers.
template<typename T>
struct unref<ref_<T> >
{
- typedef T type;
- typedef T &reference;
- typedef T &const_reference;
+ typedef T type; ///< Suitable for return by value
+ typedef T &reference; ///< Suitable for return by reference
+ typedef T &const_reference; ///< Suitable for return by const reference
};
+ /// \brief Trait for stripping top-level references
+ /// and reference wrappers.
template<typename T>
struct unref<ref_<T const> >
{
- typedef T type;
- typedef T const &reference;
- typedef T const &const_reference;
+ typedef T type; ///< Suitable for return by value
+ typedef T const &reference; ///< Suitable for return by reference
+ typedef T const &const_reference; ///< Suitable for return by const reference
};
+ /// \brief Trait for stripping top-level references
+ /// and reference wrappers.
template<typename T>
struct unref<T &>
{
- typedef T type;
- typedef T &reference;
- typedef T &const_reference;
+ typedef T type; ///< Suitable for return by value
+ typedef T &reference; ///< Suitable for return by reference
+ typedef T &const_reference; ///< Suitable for return by const reference
};
+ /// \brief Trait for stripping top-level references
+ /// and reference wrappers.
template<typename T>
struct unref<T const &>
{
- typedef T type;
- typedef T const &reference;
- typedef T const &const_reference;
+ typedef T type; ///< Suitable for return by value
+ typedef T const &reference; ///< Suitable for return by reference
+ typedef T const &const_reference; ///< Suitable for return by const reference
};
+ /// \brief Trait for stripping top-level references
+ /// and reference wrappers.
template<typename T, std::size_t N>
struct unref<T (&)[N]>
{
- typedef T (&type)[N];
- typedef T (&reference)[N];
- typedef T (&const_reference)[N];
+ typedef T (&type)[N]; ///< Suitable for return by value
+ typedef T (&reference)[N]; ///< Suitable for return by reference
+ typedef T (&const_reference)[N]; ///< Suitable for return by const reference
};
+ /// \brief Trait for stripping top-level references
+ /// and reference wrappers.
template<typename T, std::size_t N>
struct unref<T const (&)[N]>
{
- typedef T const (&type)[N];
- typedef T const (&reference)[N];
- typedef T const (&const_reference)[N];
+ typedef T const (&type)[N]; ///< Suitable for return by value
+ typedef T const (&reference)[N]; ///< Suitable for return by reference
+ typedef T const (&const_reference)[N]; ///< Suitable for return by const reference
};
}
namespace functional
{
+ /// \brief A callable PolymorphicFunctionObject equivalent
+ /// to the <tt>proto::unref()</tt> function that removes
+ /// top-level reference wrappers.
struct unref
{
+ BOOST_PROTO_CALLABLE()
+
template<typename T>
struct result;
template<typename This, typename T>
struct result<This(T)>
- : result_of::unref<BOOST_PROTO_UNCVREF(T)>
- {};
-
+ {
+ typedef BOOST_PROTO_UNCVREF(T) uncvref_type;
+ typedef typename result_of::unref<uncvref_type>::type type;
+ };
+
+ /// \brief Remove a top-level <tt>ref_\<\></tt> reference wrapper,
+ /// if it exists.
+ /// \param t The object to unwrap
+ /// \return If \c T t is a <tt>ref_\<\></tt>, return <tt>t.expr</tt>.
+ /// Otherwise, return \c t.
template<typename T>
T &operator()(T &t) const
{
return t;
}
+ /// \overload
+ ///
template<typename T>
T const &operator()(T const &t) const
{
return t;
}
+ /// \overload
+ ///
template<typename T>
T &operator()(ref_<T> &t) const
{
return t.expr;
}
+ /// \overload
+ ///
template<typename T>
T &operator()(ref_<T> const &t) const
{
@@ -169,7 +212,41 @@
};
}
- functional::unref const unref = {};
+ /// \brief Remove a top-level <tt>ref_\<\></tt> reference wrapper, if
+ /// it exists.
+ /// \param t The object to unwrap
+ /// \throw nothrow
+ /// \return If \c T t is a <tt>ref_\<\></tt>, return <tt>t.expr</tt>.
+ /// Otherwise, return \c t.
+ template<typename T>
+ T &unref(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T))
+ {
+ return t;
+ }
+
+ /// \overload
+ ///
+ template<typename T>
+ T const &unref(T const &t)
+ {
+ return t;
+ }
+
+ /// \overload
+ ///
+ template<typename T>
+ T &unref(ref_<T> &t)
+ {
+ return t.expr;
+ }
+
+ /// \overload
+ ///
+ template<typename T>
+ T &unref(ref_<T> const &t)
+ {
+ return t.expr;
+ }
}}
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
Modified: trunk/boost/xpressive/proto/transform/bind.hpp
==============================================================================
--- trunk/boost/xpressive/proto/transform/bind.hpp (original)
+++ trunk/boost/xpressive/proto/transform/bind.hpp 2008-02-21 02:18:24 EST (Thu, 21 Feb 2008)
@@ -24,6 +24,14 @@
namespace transform
{
+ /// \brief A PrimitiveTransform that uses <tt>make\<\></tt> to build
+ /// a CallableTransform, and then uses <tt>call\<\></tt> to apply it.
+ ///
+ /// <tt>bind\<\></tt> is useful as a higher-order transform, when the
+ /// transform to be applied depends on the current state of the
+ /// transformation. The invocation of the <tt>make\<\></tt> transform
+ /// evaluates any nested transforms, and the resulting type is treated
+ /// as a CallableTransform, which is evaluated with <tt>call\<\></tt>.
template<typename Fun>
struct bind : proto::callable
{
@@ -33,15 +41,22 @@
template<typename This, typename Expr, typename State, typename Visitor>
struct result<This(Expr, State, Visitor)>
{
- typedef call<typename make<Fun>::template result<void(Expr, State, Visitor)>::type> impl;
- typedef typename impl::template result<void(Expr, State, Visitor)>::type type;
+ typedef typename make<Fun>::template result<void(Expr, State, Visitor)>::type make_;
+ typedef call<make_> call_;
+ typedef typename call_::template result<void(Expr, State, Visitor)>::type type;
};
+ /// \brief Build a CallableTransform by applying <tt>make\<\></tt>
+ /// and evaluate it with <tt>call\<\></tt>
+ /// \param expr The current expression
+ /// \param state The current state
+ /// \param visitor An arbitrary visitor
+ /// \return <tt>result\<void(Expr, State, Visitor)\>::::call_()(expr, state, visitor)</tt>
template<typename Expr, typename State, typename Visitor>
typename result<void(Expr, State, Visitor)>::type
operator ()(Expr const &expr, State const &state, Visitor &visitor) const
{
- return call<typename make<Fun>::template result<void(Expr, State, Visitor)>::type>()(expr, state, visitor);
+ return typename result<void(Expr, State, Visitor)>::call_()(expr, state, visitor);
}
};
@@ -65,6 +80,14 @@
#define N BOOST_PP_ITERATION()
+ /// \brief A PrimitiveTransform that uses <tt>make\<\></tt> to build
+ /// a CallableTransform, and then uses <tt>call\<\></tt> to apply it.
+ ///
+ /// <tt>bind\<\></tt> is useful as a higher-order transform, when the
+ /// transform to be applied depends on the current state of the
+ /// transformation. The invocation of the <tt>make\<\></tt> transform
+ /// evaluates any nested transforms, and the resulting type is treated
+ /// as a CallableTransform, which is evaluated with <tt>call\<\></tt>.
template<typename Return BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
struct bind<Return(BOOST_PP_ENUM_PARAMS(N, A))> : proto::callable
{
@@ -74,17 +97,22 @@
template<typename This, typename Expr, typename State, typename Visitor>
struct result<This(Expr, State, Visitor)>
{
- typedef call<typename make<Return>::template result<void(Expr, State, Visitor)>::type(BOOST_PP_ENUM_PARAMS(N, A))> impl;
- typedef typename impl::template result<void(Expr, State, Visitor)>::type type;
+ typedef typename make<Return>::template result<void(Expr, State, Visitor)>::type make_;
+ typedef call<make_(BOOST_PP_ENUM_PARAMS(N, A))> call_;
+ typedef typename call_::template result<void(Expr, State, Visitor)>::type type;
};
+ /// \brief Build a CallableTransform by applying <tt>make\<\></tt>
+ /// and evaluate it with <tt>call\<\></tt>
+ /// \param expr The current expression
+ /// \param state The current state
+ /// \param visitor An arbitrary visitor
+ /// \return <tt>result\<void(Expr, State, Visitor)\>::::call_()(expr, state, visitor)</tt>
template<typename Expr, typename State, typename Visitor>
typename result<void(Expr, State, Visitor)>::type
operator ()(Expr const &expr, State const &state, Visitor &visitor) const
{
- return call<
- typename make<Return>::template result<void(Expr, State, Visitor)>::type(BOOST_PP_ENUM_PARAMS(N, A))
- >()(expr, state, visitor);
+ return typename result<void(Expr, State, Visitor)>::call_()(expr, state, visitor);
}
};
Modified: trunk/boost/xpressive/proto/transform/call.hpp
==============================================================================
--- trunk/boost/xpressive/proto/transform/call.hpp (original)
+++ trunk/boost/xpressive/proto/transform/call.hpp 2008-02-21 02:18:24 EST (Thu, 21 Feb 2008)
@@ -14,6 +14,7 @@
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
+ #include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/utility/result_of.hpp>
@@ -175,14 +176,64 @@
return f(expr, state);
}
};
- }
+ } // namespace detail
- template<typename Fun>
- struct call : Fun
+ /// \brief Wrap \c PrimitiveTransform so that <tt>when\<\></tt> knows
+ /// it is callable. Requires that the parameter is actually a
+ /// PrimitiveTransform.
+ ///
+ /// This form of <tt>call\<\></tt> is useful for annotating an
+ /// arbitrary PrimitiveTransform as callable when using it with
+ /// <tt>when\<\></tt>. Consider the following transform, which
+ /// is parameterized with another transform.
+ ///
+ /// \code
+ /// template<typename Grammar>
+ /// struct Foo
+ /// : when<
+ /// posit<Grammar>
+ /// , Grammar(_arg) // May or may not work.
+ /// >
+ /// {};
+ /// \endcode
+ ///
+ /// The problem with the above is that <tt>when\<\></tt> may or
+ /// may not recognize \c Grammar as callable, depending on how
+ /// \c Grammar is implemented. (See <tt>is_callable\<\></tt> for
+ /// a discussion of this issue.) The above code can guard against
+ /// the issue by wrapping \c Grammar in <tt>call\<\></tt>, such
+ /// as:
+ ///
+ /// \code
+ /// template<typename Grammar>
+ /// struct Foo
+ /// : when<
+ /// posit<Grammar>
+ /// , call<Grammar>(_arg) // OK, this works
+ /// >
+ /// {};
+ /// \endcode
+ ///
+ /// The above could also have been written as:
+ ///
+ /// \code
+ /// template<typename Grammar>
+ /// struct Foo
+ /// : when<
+ /// posit<Grammar>
+ /// , call<Grammar(_arg)> // OK, this works, too
+ /// >
+ /// {};
+ /// \endcode
+ template<typename PrimitiveTransform>
+ struct call : PrimitiveTransform
{
BOOST_PROTO_CALLABLE()
};
+ /// \brief Either call the PolymorphicFunctionObject with 0
+ /// arguments, or invoke the PrimitiveTransform with 3
+ /// arguments.
template<typename Fun>
struct call<Fun()> : proto::callable
{
@@ -192,6 +243,9 @@
template<typename This, typename Expr, typename State, typename Visitor>
struct result<This(Expr, State, Visitor)>
{
+ /// If \c Fun is a nullary PolymorphicFunctionObject, \c type is a typedef
+ /// for <tt>boost::result_of\<Fun()\>::::type</tt>. Otherwise, it is
+ /// a typedef for <tt>boost::result_of\<Fun(Expr, State, Visitor)\>::::type</tt>.
typedef
typename detail::call0<
Fun
@@ -202,6 +256,16 @@
type;
};
+ /// Either call the PolymorphicFunctionObject \c Fun with 0 arguments; or
+ /// invoke the PrimitiveTransform \c Fun with 3 arguments: the current
+ /// expression, state, and visitor.
+ ///
+ /// If \c Fun is a nullary PolymorphicFunctionObject, return <tt>Fun()()</tt>.
+ /// Otherwise, return <tt>Fun()(expr, state, visitor)</tt>.
+ ///
+ /// \param expr The current expression
+ /// \param state The current state
+ /// \param visitor An arbitrary visitor
template<typename Expr, typename State, typename Visitor>
typename result<void(Expr, State, Visitor)>::type
operator ()(Expr const &expr, State const &state, Visitor &visitor) const
@@ -219,8 +283,11 @@
}
};
- template<typename Fun, typename Arg0>
- struct call<Fun(Arg0)> : proto::callable
+ /// \brief Either call the PolymorphicFunctionObject with 1
+ /// argument, or invoke the PrimitiveTransform with 3
+ /// arguments.
+ template<typename Fun, typename A0>
+ struct call<Fun(A0)> : proto::callable
{
template<typename Sig>
struct result;
@@ -228,16 +295,35 @@
template<typename This, typename Expr, typename State, typename Visitor>
struct result<This(Expr, State, Visitor)>
{
+ /// Let \c x be <tt>when\<_, A0\>()(expr, state, visitor)</tt> and \c X
+ /// be the type of \c x.
+ /// If \c Fun is a unary PolymorphicFunctionObject that accepts \c x,
+ /// then \c type is a typedef for <tt>boost::result_of\<Fun(X)\>::::type</tt>.
+ /// Otherwise, it is a typedef for <tt>boost::result_of\<Fun(X, State, Visitor)\>::::type</tt>.
typedef
typename detail::call1<
Fun
- , typename when<_, Arg0>::template result<void(Expr, State, Visitor)>::type
+ , typename when<_, A0>::template result<void(Expr, State, Visitor)>::type
, State
, Visitor
>::type
type;
};
+ /// Either call the PolymorphicFunctionObject with 1 argument:
+ /// the result of applying the \c A0 transform; or
+ /// invoke the PrimitiveTransform with 3 arguments:
+ /// result of applying the \c A0 transform, the state, and the
+ /// visitor.
+ ///
+ /// Let \c x be <tt>when\<_, A0\>()(expr, state, visitor)</tt>.
+ /// If \c Fun is a unary PolymorphicFunctionObject that accepts \c x,
+ /// then return <tt>Fun()(x)</tt>. Otherwise, return
+ /// <tt>Fun()(x, state, visitor)</tt>.
+ ///
+ /// \param expr The current expression
+ /// \param state The current state
+ /// \param visitor An arbitrary visitor
template<typename Expr, typename State, typename Visitor>
typename result<void(Expr, State, Visitor)>::type
operator ()(Expr const &expr, State const &state, Visitor &visitor) const
@@ -245,22 +331,25 @@
typedef
detail::call1<
Fun
- , typename when<_, Arg0>::template result<void(Expr, State, Visitor)>::type
+ , typename when<_, A0>::template result<void(Expr, State, Visitor)>::type
, State
, Visitor
>
impl;
return impl::call(
- detail::as_lvalue(when<_, Arg0>()(expr, state, visitor))
+ detail::as_lvalue(when<_, A0>()(expr, state, visitor))
, state
, visitor
);
}
};
- template<typename Fun, typename Arg0, typename Arg1>
- struct call<Fun(Arg0, Arg1)> : proto::callable
+ /// \brief Either call the PolymorphicFunctionObject with 2
+ /// arguments, or invoke the PrimitiveTransform with 3
+ /// arguments.
+ template<typename Fun, typename A0, typename A1>
+ struct call<Fun(A0, A1)> : proto::callable
{
template<typename Sig>
struct result;
@@ -268,16 +357,40 @@
template<typename This, typename Expr, typename State, typename Visitor>
struct result<This(Expr, State, Visitor)>
{
+ /// Let \c x be <tt>when\<_, A0\>()(expr, state, visitor)</tt> and \c X
+ /// be the type of \c x.
+ /// Let \c y be <tt>when\<_, A1\>()(expr, state, visitor)</tt> and \c Y
+ /// be the type of \c y.
+ /// If \c Fun is a binary PolymorphicFunction object that accepts \c x
+ /// and \c y, then \c type is a typedef for
+ /// <tt>boost::result_of\<Fun(X, Y)\>::::type</tt>. Otherwise, it is
+ /// a typedef for <tt>boost::result_of\<Fun(X, Y, Visitor)\>::::type</tt>.
typedef
typename detail::call2<
Fun
- , typename when<_, Arg0>::template result<void(Expr, State, Visitor)>::type
- , typename when<_, Arg1>::template result<void(Expr, State, Visitor)>::type
+ , typename when<_, A0>::template result<void(Expr, State, Visitor)>::type
+ , typename when<_, A1>::template result<void(Expr, State, Visitor)>::type
, Visitor
>::type
type;
};
+ /// Either call the PolymorphicFunctionObject with 2 arguments:
+ /// the result of applying the \c A0 transform, and the
+ /// result of applying the \c A1 transform; or invoke the
+ /// PrimitiveTransform with 3 arguments: the result of applying
+ /// the \c A0 transform, the result of applying the \c A1
+ /// transform, and the visitor.
+ ///
+ /// Let \c x be <tt>when\<_, A0\>()(expr, state, visitor)</tt>.
+ /// Let \c y be <tt>when\<_, A1\>()(expr, state, visitor)</tt>.
+ /// If \c Fun is a binary PolymorphicFunction object that accepts \c x
+ /// and \c y, return <tt>Fun()(x, y)</tt>. Otherwise, return
+ /// <tt>Fun()(x, y, visitor)</tt>.
+ ///
+ /// \param expr The current expression
+ /// \param state The current state
+ /// \param visitor An arbitrary visitor
template<typename Expr, typename State, typename Visitor>
typename result<void(Expr, State, Visitor)>::type
operator ()(Expr const &expr, State const &state, Visitor &visitor) const
@@ -285,22 +398,26 @@
typedef
detail::call2<
Fun
- , typename when<_, Arg0>::template result<void(Expr, State, Visitor)>::type
- , typename when<_, Arg1>::template result<void(Expr, State, Visitor)>::type
+ , typename when<_, A0>::template result<void(Expr, State, Visitor)>::type
+ , typename when<_, A1>::template result<void(Expr, State, Visitor)>::type
, Visitor
>
impl;
return impl::call(
- detail::as_lvalue(when<_, Arg0>()(expr, state, visitor))
- , detail::as_lvalue(when<_, Arg1>()(expr, state, visitor))
+ detail::as_lvalue(when<_, A0>()(expr, state, visitor))
+ , detail::as_lvalue(when<_, A1>()(expr, state, visitor))
, visitor
);
}
};
- template<typename Fun, typename Arg0, typename Arg1, typename Arg2>
- struct call<Fun(Arg0, Arg1, Arg2)> : proto::callable
+ /// \brief Call the PolymorphicFunctionObject or the
+ /// PrimitiveTransform with the current expression, state
+ /// and visitor, transformed according to \c A0, \c A1, and
+ /// \c A2, respectively.
+ template<typename Fun, typename A0, typename A1, typename A2>
+ struct call<Fun(A0, A1, A2)> : proto::callable
{
template<typename Sig>
struct result;
@@ -308,26 +425,29 @@
template<typename This, typename Expr, typename State, typename Visitor>
struct result<This(Expr, State, Visitor)>
{
- typedef
- typename boost::result_of<
- Fun(
- typename when<_, Arg0>::template result<void(Expr, State, Visitor)>::type
- , typename when<_, Arg1>::template result<void(Expr, State, Visitor)>::type
- , typename when<_, Arg2>::template result<void(Expr, State, Visitor)>::type
- )
- >::type
- type;
+ typedef typename when<_, A0>::template result<void(Expr, State, Visitor)>::type a0;
+ typedef typename when<_, A1>::template result<void(Expr, State, Visitor)>::type a1;
+ typedef typename when<_, A2>::template result<void(Expr, State, Visitor)>::type a2;
+ typedef typename boost::result_of<Fun(a0, a1, a2)>::type type;
};
+ /// Let \c x be <tt>when\<_, A0\>()(expr, state, visitor)</tt>.
+ /// Let \c y be <tt>when\<_, A1\>()(expr, state, visitor)</tt>.
+ /// Let \c z be <tt>when\<_, A2\>()(expr, state, visitor)</tt>.
+ /// Return <tt>Fun()(x, y, z)</tt>.
+ ///
+ /// \param expr The current expression
+ /// \param state The current state
+ /// \param visitor An arbitrary visitor
template<typename Expr, typename State, typename Visitor>
typename result<void(Expr, State, Visitor)>::type
operator ()(Expr const &expr, State const &state, Visitor &visitor) const
{
Fun f;
return f(
- detail::as_lvalue(when<_, Arg0>()(expr, state, visitor))
- , detail::as_lvalue(when<_, Arg1>()(expr, state, visitor))
- , detail::uncv(when<_, Arg2>()(expr, state, visitor)) // HACK
+ detail::as_lvalue(when<_, A0>()(expr, state, visitor))
+ , detail::as_lvalue(when<_, A1>()(expr, state, visitor))
+ , detail::uncv(when<_, A2>()(expr, state, visitor)) // HACK
);
}
};
@@ -353,6 +473,9 @@
#define N BOOST_PP_ITERATION()
+ /// \brief Call the PolymorphicFunctionObject \c Fun with the
+ /// current expression, state and visitor, transformed according
+ /// to \c A0 through \c AN.
template<typename Fun BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
struct call<Fun(BOOST_PP_ENUM_PARAMS(N, A))> : proto::callable
{
@@ -362,15 +485,30 @@
template<typename This, typename Expr, typename State, typename Visitor>
struct result<This(Expr, State, Visitor)>
{
+ #define TMP(Z, M, DATA) \
+ typedef \
+ typename when<_, BOOST_PP_CAT(A, M)> \
+ ::template result<void(Expr, State, Visitor)> \
+ ::type \
+ BOOST_PP_CAT(a, M); \
+ /**/
+ BOOST_PP_REPEAT(N, TMP, ~)
+ #undef TMP
+
typedef
typename boost::result_of<
- #define TMP(Z, M, DATA) typename when<_, BOOST_PP_CAT(A, M)>::template result<void(Expr, State, Visitor)>::type
- Fun(BOOST_PP_ENUM(N, TMP, ~))
- #undef TMP
+ Fun(BOOST_PP_ENUM_PARAMS(N, a))
>::type
type;
};
+ /// Let \c ax be <tt>when\<_, Ax\>()(expr, state, visitor)</tt>
+ /// for each \c x in <tt>[0,N]</tt>.
+ /// Return <tt>Fun()(a0, a1,... aN)</tt>.
+ ///
+ /// \param expr The current expression
+ /// \param state The current state
+ /// \param visitor An arbitrary visitor
template<typename Expr, typename State, typename Visitor>
typename result<void(Expr, State, Visitor)>::type
operator ()(Expr const &expr, State const &state, Visitor &visitor) const
Modified: trunk/boost/xpressive/proto/transform/fold.hpp
==============================================================================
--- trunk/boost/xpressive/proto/transform/fold.hpp (original)
+++ trunk/boost/xpressive/proto/transform/fold.hpp 2008-02-21 02:18:24 EST (Thu, 21 Feb 2008)
@@ -25,11 +25,11 @@
#include <boost/xpressive/proto/proto_fwd.hpp>
#include <boost/xpressive/proto/fusion.hpp>
#include <boost/xpressive/proto/traits.hpp>
+ #include <boost/xpressive/proto/transform/call.hpp>
#include <boost/xpressive/proto/detail/suffix.hpp>
namespace boost { namespace proto
{
-
namespace transform
{
@@ -159,6 +159,8 @@
} // namespace detail
+ /// \brief A PrimitiveTransform that invokes the <tt>fusion::fold\<\></tt>
+ /// algorithm to accumulate
template<typename Sequence, typename State0, typename Fun>
struct fold : proto::callable
{
@@ -168,19 +170,39 @@
template<typename This, typename Expr, typename State, typename Visitor>
struct result<This(Expr, State, Visitor)>
{
+ /// \brief A Fusion sequence.
typedef
typename when<_, Sequence>::template result<void(Expr, State, Visitor)>::type
sequence;
+ /// \brief An initial state for the fold.
+ typedef
+ typename when<_, State0>::template result<void(Expr, State, Visitor)>::type
+ state0;
+
+ /// \brief <tt>fun(v)(e,s) == when\<_,Fun\>()(e,s,v)</tt>
+ typedef
+ detail::as_callable<Fun, Visitor>
+ fun;
+
typedef
typename fusion::BOOST_PROTO_FUSION_RESULT_OF::fold<
BOOST_PROTO_AS_FUSION_SEQUENCE_TYPE(sequence)
- , typename when<_, State0>::template result<void(Expr, State, Visitor)>::type
- , detail::as_callable<Fun, Visitor>
+ , state0
+ , fun
>::type
type;
};
+ /// Let \c seq be <tt>when\<_, Sequence\>()(expr, state, visitor)</tt>, let
+ /// \c state0 be <tt>when\<_, State0\>()(expr, state, visitor)</tt>, and
+ /// let \c fun(visitor) be an object such that <tt>fun(visitor)(expr, state)</tt>
+ /// is equivalent to <tt>when\<_, Fun\>()(expr, state, visitor)</tt>. Then, this
+ /// function returns <tt>fusion::fold(seq, state0, fun(visitor))</tt>.
+ ///
+ /// \param expr The current expression
+ /// \param state The current state
+ /// \param visitor An arbitrary visitor
template<typename Expr, typename State, typename Visitor>
typename result<void(Expr, State, Visitor)>::type
operator ()(Expr const &expr, State const &state, Visitor &visitor) const
@@ -195,9 +217,15 @@
}
};
- template<typename Sequence, typename State, typename Fun>
+ /// \brief A PrimitiveTransform that is the same as the
+ /// <tt>fold\<\></tt> transform, except that it folds
+ /// back-to-front instead of front-to-back. It uses
+ /// the \c _reverse callable PolymorphicFunctionObject
+ /// to create a <tt>fusion::reverse_view\<\></tt> of the
+ /// sequence before invoking <tt>fusion::fold\<\></tt>.
+ template<typename Sequence, typename State0, typename Fun>
struct reverse_fold
- : fold<_reverse(Sequence), State, Fun>
+ : fold<call<_reverse(Sequence)>, State0, Fun>
{};
// This specialization is only for improved compile-time performance
Modified: trunk/boost/xpressive/proto/transform/fold_tree.hpp
==============================================================================
--- trunk/boost/xpressive/proto/transform/fold_tree.hpp (original)
+++ trunk/boost/xpressive/proto/transform/fold_tree.hpp 2008-02-21 02:18:24 EST (Thu, 21 Feb 2008)
@@ -24,28 +24,62 @@
namespace detail
{
template<typename Tag>
- struct is_tag : proto::callable
+ struct has_tag : proto::callable
{
- template<typename Sig>
- struct result;
+ template<typename Sig, typename EnableIf = Tag>
+ struct result
+ : mpl::false_
+ {};
template<typename This, typename Expr, typename State, typename Visitor>
- struct result<This(Expr, State, Visitor)>
- : is_same<Tag, typename Expr::proto_tag>
+ struct result<This(Expr, State, Visitor), typename Expr::proto_tag>
+ : mpl::true_
{};
};
template<typename Tag, typename Fun>
struct fold_tree_
- : if_<is_tag<Tag>, fold<_, _state, fold_tree_<Tag, Fun> >, Fun>
+ : if_<has_tag<Tag>, fold<_, _state, fold_tree_<Tag, Fun> >, Fun>
{};
template<typename Tag, typename Fun>
struct reverse_fold_tree_
- : if_<is_tag<Tag>, reverse_fold<_, _state, reverse_fold_tree_<Tag, Fun> >, Fun>
+ : if_<has_tag<Tag>, reverse_fold<_, _state, reverse_fold_tree_<Tag, Fun> >, Fun>
{};
}
+ /// \brief A PrimitiveTransform that recursively applies the
+ /// <tt>fold\<\></tt> transform to sub-trees that all share a common
+ /// tag type.
+ ///
+ /// <tt>fold_tree\<\></tt> is useful for flattening trees into lists;
+ /// for example, you might use <tt>fold_tree\<\></tt> to flatten an
+ /// expression tree like <tt>a | b | c</tt> into a Fusion list like
+ /// <tt>cons(c, cons(b, cons(a)))</tt>.
+ ///
+ /// <tt>fold_tree\<\></tt> is easily understood in terms of a
+ /// <tt>recurse_if_\<\></tt> helper, defined as follows:
+ ///
+ /// \code
+ /// template<typename Tag, typename Fun>
+ /// struct recurse_if_
+ /// : if_<
+ /// // If the current node has type type "Tag" ...
+ /// is_same<tag_of<_>, Tag>()
+ /// // ... recurse, otherwise ...
+ /// , fold<_, _state, recurse_if_<Tag, Fun> >
+ /// // ... apply the Fun transform.
+ /// , Fun
+ /// >
+ /// {};
+ /// \endcode
+ ///
+ /// With <tt>recurse_if_\<\></tt> as defined above,
+ /// <tt>fold_tree\<Sequence, State0, Fun\>()(expr, state, visitor)</tt> is
+ /// equivalent to
+ /// <tt>fold<Sequence, State0, recurse_if_<Expr::proto_tag, Fun> >()(expr, state, visitor).</tt>
+ /// It has the effect of folding a tree front-to-back, recursing into
+ /// child nodes that share a tag type with the parent node.
template<typename Sequence, typename State0, typename Fun>
struct fold_tree
: proto::callable
@@ -56,29 +90,65 @@
template<typename This, typename Expr, typename State, typename Visitor>
struct result<This(Expr, State, Visitor)>
{
- typedef fold<
- Sequence
- , State0
- , detail::fold_tree_<typename Expr::proto_tag, Fun>
- > impl;
+ /// \brief <tt>recurse_if_\<Expr::proto_tag, Fun\></tt>, as described below.
+ typedef
+ detail::fold_tree_<typename Expr::proto_tag, Fun>
+ recurse_if_;
+ typedef fold<Sequence, State0, recurse_if_> impl;
typedef typename impl::template result<void(Expr, State, Visitor)>::type type;
};
+ /// Let \c R be <tt>recurse_if_\<Expr::proto_tag,Fun\></tt> as described below.
+ /// This function returns <tt>fold\<Sequence, State0, R\>()(expr, state, visitor)</tt>.
+ ///
+ /// \param expr The current expression
+ /// \param state The current state
+ /// \param visitor An arbitrary visitor
template<typename Expr, typename State, typename Visitor>
typename result<void(Expr, State, Visitor)>::type
operator ()(Expr const &expr, State const &state, Visitor &visitor) const
{
- typedef fold<
- Sequence
- , State0
- , detail::fold_tree_<typename Expr::proto_tag, Fun>
- > impl;
+ typedef
+ detail::fold_tree_<typename Expr::proto_tag, Fun>
+ recurse_if_;
- return impl()(expr, state, visitor);
+ return fold<Sequence, State0, recurse_if_>()(expr, state, visitor);
}
};
+ /// \brief A PrimitiveTransform that recursively applies the
+ /// <tt>reverse_fold\<\></tt> transform to sub-trees that all share
+ /// a common tag type.
+ ///
+ /// <tt>reverse_fold_tree\<\></tt> is useful for flattening trees into
+ /// lists; for example, you might use <tt>reverse_fold_tree\<\></tt> to
+ /// flatten an expression tree like <tt>a | b | c</tt> into a Fusion list
+ /// like <tt>cons(a, cons(b, cons(c)))</tt>.
+ ///
+ /// <tt>reverse_fold_tree\<\></tt> is easily understood in terms of a
+ /// <tt>recurse_if_\<\></tt> helper, defined as follows:
+ ///
+ /// \code
+ /// template<typename Tag, typename Fun>
+ /// struct recurse_if_
+ /// : if_<
+ /// // If the current node has type type "Tag" ...
+ /// is_same<tag_of<_>, Tag>()
+ /// // ... recurse, otherwise ...
+ /// , reverse_fold<_, _state, recurse_if_<Tag, Fun> >
+ /// // ... apply the Fun transform.
+ /// , Fun
+ /// >
+ /// {};
+ /// \endcode
+ ///
+ /// With <tt>recurse_if_\<\></tt> as defined above,
+ /// <tt>reverse_fold_tree\<Sequence, State0, Fun\>()(expr, state, visitor)</tt> is
+ /// equivalent to
+ /// <tt>reverse_fold<Sequence, State0, recurse_if_<Expr::proto_tag, Fun> >()(expr, state, visitor).</tt>
+ /// It has the effect of folding a tree back-to-front, recursing into
+ /// child nodes that share a tag type with the parent node.
template<typename Sequence, typename State0, typename Fun>
struct reverse_fold_tree
: proto::callable
@@ -89,26 +159,30 @@
template<typename This, typename Expr, typename State, typename Visitor>
struct result<This(Expr, State, Visitor)>
{
- typedef reverse_fold<
- Sequence
- , State0
- , detail::reverse_fold_tree_<typename Expr::proto_tag, Fun>
- > impl;
-
+ /// \brief <tt>recurse_if_\<Expr::proto_tag, Fun\></tt>, as described below.
+ typedef
+ detail::reverse_fold_tree_<typename Expr::proto_tag, Fun>
+ recurse_if_;
+
+ typedef reverse_fold<Sequence, State0, recurse_if_> impl;
typedef typename impl::template result<void(Expr, State, Visitor)>::type type;
};
+ /// Let \c R be <tt>recurse_if_\<Expr::proto_tag,Fun\></tt> as described below.
+ /// This function returns <tt>reverse_fold\<Sequence, State0, R\>()(expr, state, visitor)</tt>.
+ ///
+ /// \param expr The current expression
+ /// \param state The current state
+ /// \param visitor An arbitrary visitor
template<typename Expr, typename State, typename Visitor>
typename result<void(Expr, State, Visitor)>::type
operator ()(Expr const &expr, State const &state, Visitor &visitor) const
{
- typedef reverse_fold<
- Sequence
- , State0
- , detail::reverse_fold_tree_<typename Expr::proto_tag, Fun>
- > impl;
+ typedef
+ detail::reverse_fold_tree_<typename Expr::proto_tag, Fun>
+ recurse_if_;
- return impl()(expr, state, visitor);
+ return reverse_fold<Sequence, State0, recurse_if_>()(expr, state, visitor);
}
};
}
Modified: trunk/boost/xpressive/proto/transform/make.hpp
==============================================================================
--- trunk/boost/xpressive/proto/transform/make.hpp (original)
+++ trunk/boost/xpressive/proto/transform/make.hpp 2008-02-21 02:18:24 EST (Thu, 21 Feb 2008)
@@ -165,7 +165,37 @@
#undef TMP
}
- template<typename Fun>
+ /// \brief A PrimitiveTransform which computes a type by evaluating any
+ /// nested transforms and then constructs an object of that type.
+ ///
+ /// The <tt>make\<\></tt> transform checks to see if \c Object is a template.
+ /// If it is, the template type is disassembled to find nested transforms.
+ /// Proto considers the following types to represent transforms:
+ ///
+ /// \li Function types
+ /// \li Function pointer types
+ /// \li Types for which <tt>proto::is_callable\< type \>::::value</tt> is \c true
+ ///
+ /// <tt>make\<T\<X0,X1,...\> \>::::result\<void(Expr, State, Visitor)\>::::type</tt>
+ /// is evaluated as follows. For each \c X in <tt>X0,X1,...</tt>, do:
+ ///
+ /// \li If \c X is a template like <tt>U\<Y0,Y1,...\></tt>, then let <tt>X'</tt>
+ /// be <tt>make\<U\<Y0,Y1,...\> \>::::result\<void(Expr, State, Visitor)\>::::type</tt>
+ /// (which evaluates this procedure recursively). Note whether any
+ /// substitutions took place during this operation.
+ /// \li Otherwise, if \c X is a transform, then let <tt>X'</tt> be
+ /// <tt>when\<_, X\>::::result\<void(Expr, State, Visitor)\>::::type</tt>.
+ /// Note that a substitution took place.
+ /// \li Otherwise, let <tt>X'</tt> be \c X, and note that no substitution
+ /// took place.
+ /// \li If any substitutions took place in any of the above steps and
+ /// <tt>T\<X0',X1',...\></tt> has a nested <tt>::type</tt> typedef,
+ /// the result type is <tt>T\<X0',X1',...\>::::type</tt>.
+ /// \li Otherwise, the result type is <tt>T\<X0',X1',...\></tt>.
+ ///
+ /// Note that <tt>when\<\></tt> is implemented in terms of <tt>call\<\></tt>
+ /// and <tt>make\<\></tt>, so the above procedure is evaluated recursively.
+ template<typename Object>
struct make : proto::callable
{
template<typename Sig>
@@ -174,9 +204,13 @@
template<typename This, typename Expr, typename State, typename Visitor>
struct result<This(Expr, State, Visitor)>
{
- typedef typename detail::make_<Fun, Expr, State, Visitor>::type type;
+ typedef typename detail::make_<Object, Expr, State, Visitor>::type type;
};
+ /// \param expr The current expression
+ /// \param state The current state
+ /// \param visitor An arbitrary visitor
+ /// \return <tt>result\<void(Expr, State, Visitor)\>::::type()</tt>
template<typename Expr, typename State, typename Visitor>
typename result<void(Expr, State, Visitor)>::type
operator ()(Expr const &, State const &, Visitor &) const
@@ -192,8 +226,8 @@
/// INTERNAL ONLY
///
- template<typename Fun>
- struct is_callable<transform::make<Fun> >
+ template<typename Object>
+ struct is_callable<transform::make<Object> >
: mpl::true_
{};
@@ -273,8 +307,12 @@
};
}
- template<typename Return BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
- struct make<Return(BOOST_PP_ENUM_PARAMS(N, A))> : proto::callable
+ /// \brief A PrimitiveTransform which computes a type by evaluating any
+ /// nested transforms and then constructs an object of that type with the
+ /// current expression, state and visitor, transformed according
+ /// to \c A0 through \c AN.
+ template<typename Object BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
+ struct make<Object(BOOST_PP_ENUM_PARAMS(N, A))> : proto::callable
{
template<typename Sig>
struct result;
@@ -282,9 +320,18 @@
template<typename This, typename Expr, typename State, typename Visitor>
struct result<This(Expr, State, Visitor)>
{
- typedef typename detail::make_<Return, Expr, State, Visitor>::type type;
+ /// \brief <tt>make\<Object\>::::result\<void(Expr, State, Visitor)\>::::type</tt>
+ typedef typename detail::make_<Object, Expr, State, Visitor>::type type;
};
+ /// Let \c ax be <tt>when\<_, Ax\>()(expr, state, visitor)</tt>
+ /// for each \c x in <tt>[0,N]</tt>.
+ /// Let \c T be <tt>result\<void(Expr, State, Visitor)\>::::type</tt>.
+ /// Return <tt>T(a0, a1,... aN)</tt>.
+ ///
+ /// \param expr The current expression
+ /// \param state The current state
+ /// \param visitor An arbitrary visitor
template<typename Expr, typename State, typename Visitor>
typename result<void(Expr, State, Visitor)>::type
operator ()(Expr const &expr, State const &state, Visitor &visitor) const
Modified: trunk/libs/xpressive/proto/doc/examples.qbk
==============================================================================
--- trunk/libs/xpressive/proto/doc/examples.qbk (original)
+++ trunk/libs/xpressive/proto/doc/examples.qbk 2008-02-21 02:18:24 EST (Thu, 21 Feb 2008)
@@ -23,9 +23,9 @@
A code example is worth a thousand words ...
-[/==============================]
-[section:hello_world Hello World]
-[/==============================]
+[/=================================================================================]
+[section:hello_world Hello World: Building An Expression Template and Evaluating It]
+[/=================================================================================]
A trivial example which builds and expression template
and evaluates it.
@@ -34,9 +34,9 @@
[endsect]
-[/==================]
-[section:calc1 Calc1]
-[/==================]
+[/==================================================]
+[section:calc1 Calc1: Defining An Evaluation Context]
+[/==================================================]
A simple example which builds a miniature domain-specific
embedded language for lazy arithmetic expressions, with
@@ -46,9 +46,9 @@
[endsect]
-[/==================]
-[section:calc2 Calc2]
-[/==================]
+[/============================================================]
+[section:calc2 Calc2: Adding Members Using [^proto::extends<>]]
+[/============================================================]
An extension of the Calc1 example that uses _extends_ to
make calculator expressions valid function objects that
@@ -58,9 +58,9 @@
[endsect]
-[/==================]
-[section:calc3 Calc3]
-[/==================]
+[/===============================================]
+[section:calc3 Calc3: Defining A Simple Transform]
+[/===============================================]
An extension of the Calc2 example that uses a Proto transform
to calculate the arity of a calculator expression and statically
@@ -70,69 +70,88 @@
[endsect]
-[/==============================]
-[section:lazy_vector Lazy Vector]
-[/==============================]
-
-TODO
+[/==============================================================]
+[section:lazy_vector Lazy Vector: Controlling Operator Overloads]
+[/==============================================================]
+
+This example constructs a mini-library for linear algebra, using
+expression templates to eliminate the need for temporaries when
+adding vectors of numbers.
+
+This example uses a domain with a grammar to prune the set
+of overloaded operators. Only those operators that produce
+valid lazy vector expressions are allowed.
[LazyVector]
[endsect]
-[/==============]
-[section:rgb RGB]
-[/==============]
-
-TODO
+[/========================================================]
+[section:rgb RGB: Type Manipulations With Proto Transforms]
+[/========================================================]
+
+This is a simple example of doing arbitrary type manipulations with Proto
+transforms. It takes some expression involving primiary colors and combines
+the colors according to arbitrary rules. It is a port of the RGB example
+from _PETE_.
[RGB]
[endsect]
-[/====================]
-[section:tarray TArray]
-[/====================]
-
-TODO
+[/=====================================================]
+[section:tarray TArray: A Simple Linear Algebra Library]
+[/=====================================================]
+
+This example constructs a mini-library for linear algebra, using
+expression templates to eliminate the need for temporaries when
+adding arrays of numbers. It duplicates the TArray example from
+_PETE_.
[TArray]
[endsect]
-[/================]
-[section:vec3 Vec3]
-[/================]
-
-TODO
+[/========================================================]
+[section:vec3 Vec3: Computing With Transforms And Contexts]
+[/========================================================]
+
+This is a simple example using `proto::extends<>` to extend a terminal type
+with additional behaviors, and using custom contexts and `proto::eval()` for
+evaluating expressions. It is a port of the Vec3 example from
+_PETE_.
[Vec3]
[endsect]
-[/====================]
-[section:vector Vector]
-[/====================]
-
-TODO
+[/========================================================]
+[section:vector Vector: Adapting A Non-Proto Terminal Type]
+[/========================================================]
+
+This is an example of using `BOOST_PROTO_DEFINE_OPERATORS()` to Proto-ify
+expressions using `std::vector<>`, a non-Proto type. It is a port of the
+Vector example from _PETE_.
[Vector]
[endsect]
-[/==================]
-[section:mixed Mixed]
-[/==================]
-
-TODO
+[/=============================================================]
+[section:mixed Mixed: Adapting Several Non-Proto Terminal Types]
+[/=============================================================]
+
+This is an example of using `BOOST_PROTO_DEFINE_OPERATORS()` to Proto-ify
+expressions using `std::vector<>` and `std::list<>`, non-Proto types. It is a
+port of the Mixed example from _PETE_.
[Mixed]
[endsect]
-[/================================]
-[section:future_group Future Group]
-[/================================]
+[/===========================================================]
+[section:future_group Future Group: A More Advanced Transform]
+[/===========================================================]
An advanced example of a Proto transform that implements
Howard Hinnant's design for /future groups/ that block
Modified: trunk/libs/xpressive/proto/doc/implementation.qbk
==============================================================================
--- trunk/libs/xpressive/proto/doc/implementation.qbk (original)
+++ trunk/libs/xpressive/proto/doc/implementation.qbk 2008-02-21 02:18:24 EST (Thu, 21 Feb 2008)
@@ -7,6 +7,166 @@
[section:implementation Appendix C: Implementation Notes]
+[section:sfinae Quick-n-Dirty Type Categorization]
+
+Much has already been written about dispatching on type traits using
+SFINAE (Substitution Failure Is Not An Error) techniques in C++. There
+is a Boost library, Boost.Enable_if, to make the technique idiomatic.
+Proto dispatches on type traits extensively, but it doesn't use
+`enable_if<>` very often. Rather, it dispatches based on the presence
+or absence of nested types, often typedefs for void.
+
+Consider the implementation of `is_expr<>`. It could have been written
+as something like this:
+
+ template<typename T>
+ struct is_expr
+ : is_base_and_derived<proto::some_expr_base, T>
+ {};
+
+Rather, it is implemented as this:
+
+ template<typename T, typename Void = void>
+ struct is_expr
+ : mpl::false_
+ {};
+
+ template<typename T>
+ struct is_expr<T, typename T::proto_is_expr_>
+ : mpl::true_
+ {};
+
+This relies on the fact that the specialization will be preferred
+if `T` has a nested `proto_is_expr_` that is a typedef for `void`.
+All Proto expression types have such a nested typedef.
+
+Why does Proto do it this way? The reason is because, after running
+extensive benchmarks while trying to improve compile times, I have
+found that this approach compiles faster. It requires exactly one
+template instantiation. The other approach requires at least 2:
+`is_expr<>` and `is_base_and_derived<>`, plus whatever templates
+`is_base_and_derived<>` may instantiate.
+
+[endsect]
+
+[section:function_arity Detecting the Arity of Function Objects]
+
+In several places, Proto needs to know whether or not a function
+object `Fun` can be called with certain parameters and take a
+fallback action if not. This happens in _callable_context_ and
+in the _call_ transform. How does Proto know? It involves some
+tricky metaprogramming. Here's how.
+
+Another way of framing the question is by trying to implement
+the following `can_be_called<>` Boolean metafunction, which
+checks to see if a function object `Fun` can be called with
+parameters of type `A` and `B`:
+
+ template<typename Fun, typename A, typename B>
+ struct can_be_called;
+
+First, we define the following `dont_care` struct, which has an
+implicit conversion from anything. And not just any implicit
+conversion; it has a ellipsis conversion, which is the worst possible
+conversion for the purposes of overload resolution:
+
+ struct dont_care
+ {
+ dont_care(...);
+ };
+
+We also need some private type known only to us with an overloaded
+comma operator (!), and some functions that detect the presence of
+this type and return types with different sizes, as follows:
+
+ struct private_type
+ {
+ private_type const &operator,(int) const;
+ };
+
+ typedef char yes_type; // sizeof(yes_type) == 1
+ typedef char (&no_type)[2]; // sizeof(no_type) == 2
+
+ template<typename T>
+ no_type is_private_type(T const &);
+
+ yes_type is_private_type(private_type const &);
+
+Next, we implement a binary function object wrapper with a very
+strange conversion operator, whose meaning will become clear later.
+
+ template<typename Fun>
+ struct funwrap2 : Fun
+ {
+ funwrap2();
+ typedef private_type const &(*pointer_to_function)(dont_care, dont_care);
+ operator pointer_to_function() const;
+ };
+
+With all of these bits and pieces, we can implement `can_be_called<>` as
+follows:
+
+ template<typename Fun, typename A, typename B>
+ struct can_be_called
+ {
+ static funwrap2<Fun> &fun;
+ static A &a;
+ static B &b;
+
+ static bool const value = (
+ sizeof(no_type) == sizeof(is_private_type( (fun(a,b), 0) ))
+ );
+
+ typedef mpl::bool_<value> type;
+ };
+
+The idea is to make it so that `fun(a,b)` will always compile by adding
+our own binary function overload, but doing it in such a way that we can
+detect whether our overload was selected or not. And we rig it so that
+our overload is selected if there is really no better option. What follows
+is a description of how `can_be_called<>` works.
+
+We wrap `Fun` in a type that has an implicit conversion to a pointer to
+a binary function. An object `fun` of class type can be invoked as
+`fun(a, b)` if it has such a conversion operator, but since it involves
+a user-defined conversion operator, it is less preferred than an
+overloaded `operator()`, which requires no such conversion.
+
+The function pointer can accept any two arguments by virtue
+of the `dont_care` type. The conversion sequence for each argument is
+guaranteed to be the worst possible conversion sequence: an implicit
+conversion through an ellipsis, and a user-defined conversion to
+`dont_care`. In total, it means that `funwrap2<Fun>()(a, b)` will
+always compile, but it will select our overload only if there really is
+no better option.
+
+If there is a better option --- for example if `Fun` has an overloaded
+function call operator such as `void operator()(A a, B b)` --- then
+`fun(a, b)` will resolve to that one instead. The question now is how
+to detect which function got picked by overload resolution.
+
+Notice how `fun(a, b)` appears in `can_be_called<>`: `(fun(a, b), 0)`.
+Why do we use the comma operator there? The reason is because we are
+using this expression as the argument to a function. If the return type
+of `fun(a, b)` is `void`, it cannot legally be used as an argument to
+a function. The comma operator sidesteps the issue.
+
+This should also make plain the purpose of the overloaded comma operator
+in `private_type`. The return type of the pointer to function is
+`private_type`. If overload resolution selects our overload, then the
+type of `(fun(a, b), 0)` is `private_type`. Otherwise, it is `int`.
+That fact is used to dispatch to either overload of `is_private_type()`,
+which encodes its answer in the size of its return type.
+
+That's how it works with binary functions. Now repeat the above process
+for functions up to some predefined function arity, and you're done.
+
+[endsect]
+
+[section:ppmp_vs_tmp Avoiding Template Instiations With The Preprocessor]
+
TODO
[endsect]
+
+[endsect]
Modified: trunk/libs/xpressive/proto/doc/proto.qbk
==============================================================================
--- trunk/libs/xpressive/proto/doc/proto.qbk (original)
+++ trunk/libs/xpressive/proto/doc/proto.qbk 2008-02-21 02:18:24 EST (Thu, 21 Feb 2008)
@@ -35,6 +35,7 @@
[/ Links ]
+[def _PETE_ [@http://www.codesourcery.com/pooma/download.html PETE]]
[def _spirit_fx_ [@http://spirit.sourceforge.net Spirit Parser Framework]]
[def _spirit_ [@http://spirit.sourceforge.net Spirit]]
[def _xpressive_ [@../../../libs/xpressive/doc/index.html Boost.Xpressive]]
@@ -71,6 +72,8 @@
[def _callable_context_ [classref boost::proto::context::callable_context `callable_context<>`]]
[def _null_context_ [classref boost::proto::context::null_context `null_context<>`]]
[def _when_ [classref boost::proto::transform::when `when<>`]]
+[def _call_ [classref boost::proto::transform::call `call<>`]]
+[def _make_ [classref boost::proto::transform::make `make<>`]]
[def _flatten_ [funcref boost::proto::flatten `flatten()`]]
[include preface.qbk]
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk