⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 examples.cpp

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 CPP
📖 第 1 页 / 共 2 页
字号:
///////////////////////////////////////////////////////////////////////////////// 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 + -