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 + -
显示快捷键?