transforms.qbk

来自「Boost provides free peer-reviewed portab」· QBK 代码 · 共 1,417 行 · 第 1/4 页

QBK
1,417
字号
        typedef transform::arg    _arg;        typedef transform::left   _left;        typedef transform::right  _right;    }}These transforms are useful for extracting the ['[^N]]th argument from anexpression. The `_left` transform is equivalent to the `arg_c<0>` transform,and the `_right` transform is equivalent to the `arg_c<1>` transform.[table    [   [Expression]        [Returns]    ]    [   [`transform::arg_c<N>::result<void(Expr, State, Visitor)>::type`]        [`proto::result_of::arg_c<Expr, N>::type`]    ]    [   [`transform::arg_c<N>()(expr, state, visitor)`]        [`proto::arg_c<N>(expr)`]    ]    [   [`transform::left::result<void(Expr, State, Visitor)>::type`]        [`proto::result_of::left<Expr>::type`]    ]    [   [`transform::left()(expr, state, visitor)`]        [`proto::left(expr)`]    ]    [   [`transform::right::result<void(Expr, State, Visitor)>::type`]        [`proto::result_of::right<Expr>::type`]    ]    [   [`transform::right()(expr, state, visitor)`]        [`proto::right(expr)`]    ]]Example:    // Matches an integer terminal and extracts the int.    struct Int      : when< terminal<int>, _arg >    {};[endsect][section:identity_and_friends [^_expr], [^_state] and [^_visitor]]    namespace boost { namespace proto    {        namespace transform        {            struct expr;            struct state;            struct visitor;        }        typedef transform::expr     _expr;        typedef transform::state    _state;        typedef transform::visitor  _visitor;    }}The `expr`, `state` and `visitor` transforms merely return the`expr`, `state` and `visitor` arguments, respectively. Proto'swildcard pattern, `_`, behaves like `transform::expr` when usedas a transform.[table    [   [Expression]        [Returns]    ]    [   [`_::result<void(Expr, State, Visitor)>::type`]        [`Expr`]    ]    [   [`_()(expr_, state, visitor)`]        [`expr_`]    ]    [   [`transform::expr::result<void(Expr, State, Visitor)>::type`]        [`Expr`]    ]    [   [`transform::expr()(expr_, state, visitor)`]        [`expr_`]    ]    [   [`transform::state::result<void(Expr, State, Visitor)>::type`]        [`State`]    ]    [   [`transform::state()(expr, state_, visitor)`]        [`state_`]    ]    [   [`transform::visitor::result<void(Expr, State, Visitor)>::type`]        [`Visitor`]    ]    [   [`transform::visitor()(expr, state, visitor_)`]        [`visitor_`]    ]]Example:    // Matches a subscript expression where the left- and right-hand operands    // match MyGrammar, returns the expression unmodified    struct Subscript      : when< subscript<MyGrammar, MyGrammar>, _expr >    {};[endsect][section:if [^if_<>]]    namespace boost { namespace proto     {        namespace control        {            template<                typename If              , typename Then = _              , typename Else = not_<_>             >            struct if_;        }        using control::if_;    }}We've already seen the _if_ template in the context of grammars, but_if_ can also be used as a transform. It can be used to conditionallyapply one transform or another based on some condition. The threetemplate parameters are Proto transforms. The result of applying thefirst transform should be a compile-time Boolean. If it is true, thenthe first transform is applied. The second is applied otherwise.[table    [   [Expression]        [Returns]    ]    [   [``control::if_<If, Then, Else>    ::result<void(Expr, State, Visitor)>::type``]        [``typedef    mpl::if_<        when<_, If>::result<void(Expr, State, Visitor)>::type      , when<_, Then>      , when<_, Else>    >::typebranch;typedef branch::result<void(Expr, State, Visitor)>::type type;``]    ]    [   [`control::if_<If, Then, Else>()(expr, state, visitor)`]        [``typedef ... branch; // Same as abovebranch()(expr, state, visitor);``]    ]]Example:    // Match a terminal. If size of the terminal    // argument is less than or equal to 4, make    // a new terminal that stores the argument by    // value. Otherwise, store the argument by    // reference.    struct ByValOrRef      : when<            terminal<_>          , if_<                mpl::less_equal<                    mpl::sizeof_<_arg>                  , mpl::size_t<4>                >()              , _make_terminal(_arg)              , _make_terminal(_ref(_arg))            >        >    {};[endsect][section:and_or_not [^and_<>], [^or_<>], and [^not_<>]]    namespace boost { namespace proto     {        namespace control        {            template<typename... T>            struct and_;            template<typename... T>            struct or_;            template<typename T>            struct not_;        }        using control::and_;        using control::or_;        using control::not_;    }}As with _if_, the grammar elements _and_, _or_, and _not_ canalso be used as transforms. At a high level, here is what thetransforms do:[variablelist[ [`and_<T0,T1,...,Tn>`]  [Apply the transform `Tn`.] ][ [`or_<T0,T1,...,Tn>`]  [Apply the transform `Tx` where `x` is the lowest number   such that `matches<Expr,Tx>::value` is `true`.] ][ [`not_<T>`] [Return the current expression unchanged.] ]]The following table specifies the behaviors described above moreprecisely.[table    [   [Expression]        [Returns]    ]    [   [``control::and_<A,B,C>    ::result<void(Expr, State, Visitor)>::type``]        [`C::result<void(Expr, State, Visitor)>::type`]    ]    [   [`control::and_<A,B,C>()(expr, state, visitor)`]        [`C()(expr, state, visitor)`]    ]    [   [``control::or_<A,B,C>    ::result<void(Expr, State, Visitor)>::type``]        [``typedef mpl::if_<    matches<Expr, A>  , A  , mpl::if_<        matches<Expr, B>      , B      , C    >::type>::type which;typedef which::result<void(Expr, State, Visitor)>::type type;``]    ]    [   [`control::or_<A,B,C>()(expr, state, visitor)`]        [``typedef ... which; // Same as abovewhich()(expr, state, visitor);``]    ]    [   [``control::not_<A>    ::result<void(Expr, State, Visitor)>::type``]        [`Expr`]    ]    [   [`control::not_<A>()(expr, state, visitor)`]        [`expr`]    ]]Example:    // A transform that matches any expression and    // unwraps any reference_wrapped terminals it    // finds.    struct UnwrapReference      : or_<            // Pass through terminals that are not            // reference_wrappers unchanged:            and_<                terminal<_>              , not_<if_<is_reference_wrapper<_arg>()> >            >            // For other terminals (i.e., reference_wrapper            // terminals), unwrap the reference:          , when<                terminal<_>              , terminal<unwrap_reference<_arg> >(_arg)            >            // Otherwise, match non-terminals and            // recurse.          , when<                nary_expr<_, vararg<UnwrapReference> >            >        >    {};The above transform serves to illustrate the behaviors of the _and_,_or_, and _not_ transforms, but it is admittedly contrived. Thetransform is more easily written as follows:    // Functionally identical to the UnwrapReference    // transform above:    struct UnwrapReference      : or_<            when<                terminal<reference_wrapper<_> >              , terminal<unwrap_reference<_arg> >(_arg)            >          , terminal<_>          , nary_expr<_, vararg<UnwrapReference> >        >    {};[endsect][section:call [^call<>]]    namespace boost { namespace proto    {        namespace transform        {            template<typename Fun>            struct call;        }        using transform::call;    }}The `call<>` transform is used to invoke callable transforms and evaluatetheir arguments. When you use a callable transform as in `when< posit<_>, Callable(_arg) >`, the `call<>` transform is used behindthe scenes to evaluate `Callable(_arg)`. In fact, for any callabletransform, the following short- and long-forms are equivalent:[table    [ [Short From]      [Long Form] ]    [ [ `when< Grammar, Callable(Tran1, Tran2...) >` ]      [ `when< Grammar, call< Callable(Tran1, Tran2...) > >` ] ]]You might decide to use `call<>` explicitly in cases when Protocan't figure out that a given transform is callable. (See the discussion onthe `is_callable<>` trait TODO LINK.) Rather than specialize `proto::is_callable<>` for your transform, you can simply wrap its use in`call<>`, instead. [tip For users of legacy compilers like MSVC 7.1, `call<>` is useful to workaround compiler bugs. Doubly-nested transforms such as `Callable(_arg1(_arg2))`cause older compilers problems, but the equivalent `Callable(call<_arg1(_arg2)>)`solves the problem.]The semantics of `call<>` are described in the table below:[table    [   [Expression]        [Returns]    ]    [   [`call<Fun(A0, A1, ... AN)>::result<void(Expr, State, Visitor)>::type`]        [``boost::result_of<Fun(    when<_, A0>::result<void(Expr, State, Visitor)>::type  , when<_, A1>::result<void(Expr, State, Visitor)>::type    ...  , when<_, AN>::result<void(Expr, State, Visitor)>::type)>::type``]    ]    [   [`call<Fun(A0, A1, ... AN)>()(expr, state, visitor)`]        [``Fun()(    when<_, A0>()(expr, state, visitor)  , when<_, A1>()(expr, state, visitor)    ...  , when<_, AN>()(expr, state, visitor))``]    ]]

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?