Update of /cvsroot/boost/boost/libs/xpressive/test/proto
In directory
sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv9531/libs/xpressive/test/proto
Modified Files:
lambda.cpp
Log Message:
allow meta::binary_expr<mpl::_, Grammar, Grammar> to match any binary
expression, lambda example supports evaluation of nullary lambdas
Index: lambda.cpp
===================================================================
RCS file: /cvsroot/boost/boost/libs/xpressive/test/proto/lambda.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- lambda.cpp 30 Dec 2006 21:48:20 -0000 1.4
+++ lambda.cpp 31 Dec 2006 07:22:13 -0000 1.5
@@ -6,20 +6,24 @@
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <sstream>
-#include <boost/mpl/if.hpp>
-#include <boost/mpl/print.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/min_max.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/next_prior.hpp>
#include <boost/fusion/tuple.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/xpressive/proto/proto.hpp>
+#include <boost/xpressive/proto/transform/arg.hpp>
+#include <boost/xpressive/proto/transform/fold.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>
using namespace boost;
struct lambda_domain {};
-template<int I> struct placeholder {};
+template<typename I> struct placeholder { typedef I arity; };
template<typename Tuple>
struct lambda_context;
@@ -37,6 +41,41 @@
: add_reference<typename add_const<T>::type>
{};
+// Some custom transforms for calculating the max arity of a lambda expression
+template<typename Grammar>
+struct max_arity
+ : Grammar
+{
+ template<typename Expr, typename State, typename Visitor>
+ struct apply
+ {
+ typedef typename Grammar::template apply<Expr, State, Visitor>::type
arity;
+ typedef typename mpl::max<arity, State>::type type;
+ };
+};
+
+template<typename Grammar>
+struct placeholder_arity
+ : Grammar
+{
+ template<typename Expr, typename, typename>
+ struct apply
+ : mpl::next<typename proto::meta::arg<Expr>::type::arity>
+ {};
+};
+
+// The lambda grammar, with the transforms for calculating the max arity
+struct LambdaGrammar
+ : max_arity<
+ proto::or_<
+ placeholder_arity< proto::meta::terminal<placeholder<mpl::_> > >
+ , proto::trans::state< proto::meta::terminal<mpl::_> >
+ , proto::trans::arg< proto::meta::unary_expr<mpl::_, LambdaGrammar> >
+ , proto::trans::fold< proto::meta::binary_expr<mpl::_,
LambdaGrammar, LambdaGrammar> >
+ >
+ >
+{};
+
template<typename Tuple>
struct lambda_context_result
{
@@ -51,10 +90,10 @@
typedef Arg &type;
};
- template<typename This, int I>
+ template<typename This, typename I>
struct result<This(proto::tag::terminal, placeholder<I> const &)>
{
- typedef typename fusion::result_of::value_at_c<Tuple, I>::type type;
+ typedef typename fusion::result_of::value_at<Tuple, I>::type type;
};
#define UN_OP_RESULT(Op, Arg)\
@@ -65,8 +104,7 @@
, typename nested::type &\
, typename nested::type\
>::type type;\
- static type call(typename param<arg_type>::type arg)\
- {\
+ static type call(typename param<arg_type>::type arg) {\
return Op arg;\
}\
/**/
@@ -80,8 +118,7 @@
, typename nested::type &\
, typename nested::type\
>::type type;\
- static type call(typename param<left_type>::type left, typename
param<right_type>::type right)\
- {\
+ static type call(typename param<left_type>::type left, typename
param<right_type>::type right) {\
return left Op right;\
}\
/**/
@@ -134,8 +171,6 @@
: lambda_context_result<Tuple>
{
typedef lambda_context<Tuple> this_type;
- typedef lambda_context_result<Tuple> base_type;
- template<typename Sig> struct result_ : base_type::template result<Sig> {};
lambda_context(Tuple const &args)
: args_(args)
@@ -148,25 +183,25 @@
return arg;
}
- template<int I>
- typename fusion::result_of::at_c<Tuple, I>::type
+ template<typename I>
+ typename fusion::result_of::at<Tuple, I>::type
operator()(proto::tag::terminal, placeholder<I>)
{
- return fusion::get<I>(this->args_);
+ return fusion::at<I>(this->args_);
}
template<typename Tag, typename Arg>
- typename result_<this_type(Tag, Arg &)>::type
+ typename lambda_context_result<Tuple>::template result<this_type(Tag, Arg
&)>::type
operator()(Tag, Arg &arg)
{
- return result_<this_type(Tag, Arg &)>::call(arg.eval(*this));
+ return lambda_context_result<Tuple>::template result<this_type(Tag,
Arg &)>::call(arg.eval(*this));
}
template<typename Tag, typename Left, typename Right>
- typename result_<this_type(Tag, Left &, Right &)>::type
+ typename lambda_context_result<Tuple>::template result<this_type(Tag, Left
&, Right &)>::type
operator()(Tag, Left &left, Right &right)
{
- return result_<this_type(Tag, Left &, Right
&)>::call(left.eval(*this), right.eval(*this));
+ return lambda_context_result<Tuple>::template result<this_type(Tag,
Left &, Right &)>::call(left.eval(*this), right.eval(*this));
}
private:
@@ -189,6 +224,21 @@
using base_type::operator =;
+ // Careful not to evaluate the return type of the nullary function
+ // unless we have a nullary lambda!
+ typedef typename mpl::eval_if<
+ typename LambdaGrammar::apply<T, mpl::int_<0>, mpl::void_>::type
+ , mpl::identity<void>
+ , proto::meta::eval<T, lambda_context<fusion::tuple<> > >
+ >::type nullary_type;
+
+ nullary_type operator()() const
+ {
+ fusion::tuple<> args;
+ lambda_context<fusion::tuple<> > ctx(args);
+ return this->eval(ctx);
+ }
+
// hide base_type::operator() by defining our own which
// evaluates the lambda expression.
template<typename A0>
@@ -216,6 +266,7 @@
struct generate<lambda_domain, Expr, Tag>
{
typedef lambda<Expr> type;
+
static type make(Expr const &expr)
{
return lambda<Expr>(expr);
@@ -223,8 +274,15 @@
};
}}}
-lambda<proto::meta::terminal<placeholder<0> >::type> const _1;
-lambda<proto::meta::terminal<placeholder<1> >::type> const _2;
+lambda<proto::meta::terminal<placeholder<mpl::int_<0> > >::type> const _1;
+lambda<proto::meta::terminal<placeholder<mpl::int_<1> > >::type> const _2;
+
+template<typename T>
+lambda<typename proto::meta::terminal<T>::type> const constant(T const &t)
+{
+ typename proto::meta::terminal<T>::type that = {t};
+ return lambda<typename proto::meta::terminal<int>::type>(that);
+}
void test_lambda()
{
@@ -232,9 +290,13 @@
BOOST_CHECK_EQUAL(-11, ( (-(_1 + 2)) / 4 )(42));
BOOST_CHECK_CLOSE(2.58, ( (4 - _2) * 3 )(42, 3.14), 0.1);
+ // check non-const ref terminals
std::stringstream sout;
(sout << _1 << " -- " << _2)(42, "Life, the Universe and Everything!");
BOOST_CHECK_EQUAL("42 -- Life, the Universe and Everything!", sout.str());
+
+ // check nullary lambdas
+ BOOST_CHECK_EQUAL(3, (constant(1) + constant(2))());
}
using namespace unit_test;
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Boost-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/boost-cvs