📄 examples.cpp
字号:
///////////////////////////////////////////////////////////////////////////////// examples.hpp//// 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)#include <iostream>#include <boost/config.hpp>#include <boost/mpl/min_max.hpp>#include <boost/proto/core.hpp>#include <boost/proto/transform.hpp>#include <boost/utility/result_of.hpp>#if BOOST_VERSION < 103500# include <boost/spirit/fusion/sequence/cons.hpp># include <boost/spirit/fusion/sequence/tuple.hpp>#else# include <boost/fusion/include/cons.hpp># include <boost/fusion/include/tuple.hpp># include <boost/fusion/include/pop_front.hpp>#endif#include <boost/test/unit_test.hpp>namespace mpl = boost::mpl;namespace proto = boost::proto;namespace fusion = boost::fusion;using proto::_;template<int I>struct placeholder{};namespace test1{//[ CalcGrammar // This is the grammar for calculator expressions, // to which we will attach transforms for computing // the expressions' arity. /*<< A Calculator expression is ... >>*/ struct CalcArity : proto::or_< /*<< _1, or ... >>*/ proto::terminal< placeholder<0> > /*<< _2, or ... >>*/ , proto::terminal< placeholder<1> > /*<< some other terminal, or ... >>*/ , proto::terminal< _ > /*<< a unary expression where the operand is a calculator expression, or ... >>*/ , proto::unary_expr< _, CalcArity > /*<< a binary expression where the operands are calculator expressions >>*/ , proto::binary_expr< _, CalcArity, CalcArity > > {};//]}//[ binary_arity/*<< The `CalculatorArity` is a transform for calculatingthe arity of a calculator expression. It will be define interms of `binary_arity`, which is defined in terms of`CalculatorArity`; hence, the definition is recursive.>>*/struct CalculatorArity;// A custom transform that returns the arity of a unary// calculator expression by finding the arity of the// child expression.struct unary_arity /*<< Custom transforms should inherit from transform<>. In some cases, (e.g., when the transform is a template), it is also necessary to specialize the proto::is_callable<> trait. >>*/ : proto::transform<unary_arity>{ template<typename Expr, typename State, typename Data> /*<< Transforms have a nested `impl<>` that is a valid TR1 function object. >>*/ struct impl : proto::transform_impl<Expr, State, Data> { /*<< Get the child. >>*/ typedef typename proto::result_of::child<Expr>::type child_expr; /*<< Apply `CalculatorArity` to find the arity of the child. >>*/ typedef typename boost::result_of<CalculatorArity(child_expr, State, Data)>::type result_type; /*<< The `unary_arity` transform doesn't have an interesting runtime counterpart, so just return a default-constructed object of the correct type. >>*/ result_type operator ()(proto::ignore, proto::ignore, proto::ignore) const { return result_type(); } };};// A custom transform that returns the arity of a binary// calculator expression by finding the maximum of the// arities of the mpl::int_<2> child expressions.struct binary_arity /*<< All custom transforms should inherit from transform. In some cases, (e.g., when the transform is a template), it is also necessary to specialize the proto::is_callable<> trait. >>*/ : proto::transform<binary_arity>{ template<typename Expr, typename State, typename Data> /*<< Transforms have a nested `impl<>` that is a valid TR1 function object. >>*/ struct impl : proto::transform_impl<Expr, State, Data> { /*<< Get the left and right children. >>*/ typedef typename proto::result_of::left<Expr>::type left_expr; typedef typename proto::result_of::right<Expr>::type right_expr; /*<< Apply `CalculatorArity` to find the arity of the left and right children. >>*/ typedef typename boost::result_of<CalculatorArity(left_expr, State, Data)>::type left_arity; typedef typename boost::result_of<CalculatorArity(right_expr, State, Data)>::type right_arity; /*<< The return type is the maximum of the children's arities. >>*/ typedef typename mpl::max<left_arity, right_arity>::type result_type; /*<< The `unary_arity` transform doesn't have an interesting runtime counterpart, so just return a default-constructed object of the correct type. >>*/ result_type operator ()(proto::ignore, proto::ignore, proto::ignore) const { return result_type(); } };};//]proto::terminal< placeholder<0> >::type const _1 = {{}};proto::terminal< placeholder<1> >::type const _2 = {{}};//[ CalculatorArityGrammarstruct CalculatorArity : proto::or_< proto::when< proto::terminal< placeholder<0> >, mpl::int_<1>() > , proto::when< proto::terminal< placeholder<1> >, mpl::int_<2>() > , proto::when< proto::terminal<_>, mpl::int_<0>() > , proto::when< proto::unary_expr<_, _>, unary_arity > , proto::when< proto::binary_expr<_, _, _>, binary_arity > >{};//]//[ CalcAritystruct CalcArity : proto::or_< proto::when< proto::terminal< placeholder<0> >, mpl::int_<1>() > , proto::when< proto::terminal< placeholder<1> >, mpl::int_<2>() > , proto::when< proto::terminal<_>, mpl::int_<0>() > , proto::when< proto::unary_expr<_, CalcArity>, CalcArity(proto::_child) > , proto::when< proto::binary_expr<_, CalcArity, CalcArity>, mpl::max<CalcArity(proto::_left), CalcArity(proto::_right)>() > >{};//]// BUGBUG find workaround for this#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)#define _pop_front(x) call<proto::_pop_front(x)>#define _value(x) call<proto::_value(x)>#endif//[ AsArgList// This transform matches function invocations such as foo(1,'a',"b")// and transforms them into Fusion cons lists of their arguments. In this// case, the result would be cons(1, cons('a', cons("b", nil()))).struct ArgsAsList : proto::when< proto::function<proto::terminal<_>, proto::vararg<proto::terminal<_> > > /*<< Use a `reverse_fold<>` transform to iterate over the children of this node in reverse order, building a fusion list from back to front. >>*/ , proto::reverse_fold< /*<< The first child expression of a `function<>` node is the function being invoked. We don't want that in our list, so use `pop_front()` to remove it. >>*/ proto::_pop_front(_) /*<< `nil` is the initial state used by the `reverse_fold<>` transform. >>*/ , fusion::nil() /*<< Put the rest of the function arguments in a fusion cons list. >>*/ , fusion::cons<proto::_value, proto::_state>(proto::_value, proto::_state) > >{};//]//[ FoldTreeToList// This transform matches expressions of the form (_1=1,'a',"b")// (note the use of the comma operator) and transforms it into a// Fusion cons list of their arguments. In this case, the result// would be cons(1, cons('a', cons("b", nil()))).struct FoldTreeToList : proto::or_< // This grammar describes what counts as the terminals in expressions // of the form (_1=1,'a',"b"), which will be flattened using // reverse_fold_tree<> below. proto::when< proto::assign<_, proto::terminal<_> > , proto::_value(proto::_right) > , proto::when< proto::terminal<_> , proto::_value > , proto::when< proto::comma<FoldTreeToList, FoldTreeToList> /*<< Fold all terminals that are separated by commas into a Fusion cons list. >>*/ , proto::reverse_fold_tree< _ , fusion::nil() , fusion::cons<FoldTreeToList, proto::_state>(FoldTreeToList, proto::_state) > > >{};//]//[ Promote// This transform finds all float terminals in an expression and promotes// them to doubles.struct Promote : proto::or_< /*<< Match a `terminal<float>`, then construct a `terminal<double>::type` with the `float`. >>*/ proto::when<proto::terminal<float>, proto::terminal<double>::type(proto::_value) > , proto::when<proto::terminal<_> > /*<< `nary_expr<>` has a pass-through transform which will transform each child sub-expression using the `Promote` transform. >>*/ , proto::when<proto::nary_expr<_, proto::vararg<Promote> > > >{};//]//[ LazyMakePairstruct make_pair_tag {};proto::terminal<make_pair_tag>::type const make_pair_ = {{}};// This transform matches lazy function invocations like// `make_pair_(1, 3.14)` and actually builds a `std::pair<>`
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -