back_end.qbk

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

QBK
1,356
字号
        std::ctype<char> const &ct(std::use_facet<std::ctype<char> >(loc));        // Concatenate and widen the string expression        StringCopy()(expr, &buffer[0], ct);        // Write out the buffer.        std::wcout << buffer << std::endl;    }    int main()    {        widen( proto::lit("hello") + " " + "world" );    }The above code displays:[prehello world]This is a rather round-about way of demonstrating that you can pass extra data to a transform as a third parameter. There are no restrictions on what this parameter can be, and (unlike the state parameter) Proto will never mess with it.[heading Implicit Parameters to Primitive Transforms]Let's use the above example to illustrate some other niceties of Proto transforms. We've seen that grammars, when used as function objects, can accept up to 3 parameters, and that when using these grammars in callable transforms, you can also specify up to 3 parameters. Let's take another look at the transform associated with non-terminals above:    StringCopy(        proto::_right      , StringCopy(proto::_left, proto::_state, proto::_data)      , proto::_data    )Here we specify all three parameters to both invocations of the `StringCopy` grammar. But we don't have to specify all three. If we don't specify a third parameter, `proto::_data` is assumed. Likewise for the second parameter and `proto::_state`. So the above transform could have been written more simply as:    StringCopy(        proto::_right      , StringCopy(proto::_left)    )The same is true for any primitive transform. The following are all equivalent:[table Implicit Parameters to Primitive Transforms  [[Equivalent Transforms]]  [[`proto::when<_, StringCopy>`]]  [[`proto::when<_, StringCopy(_)>`]]  [[`proto::when<_, StringCopy(_, proto::_state)>`]]  [[`proto::when<_, StringCopy(_, proto::_state, proto::_data)>`]]][note *Grammars Are Primitive Transforms Are Function Objects*So far, we've said that all Proto grammars are function objects. But it's more accurate to say that Proto grammars are primitive transforms -- a special kind of function object that takes between 1 and 3 arguments, and that Proto knows to treat specially when used in a callable transform, as in the table above.][note *Not All Function Objects Are Primitive Transforms*You might be tempted now to drop the `_state` and `_data` parameters to `WidenCopy(proto::_value, proto::_state, proto::_data)`. That would be an error. `WidenCopy` is just a plain function object, not a primitive transform, so you must specify all its arguments. We'll see later how to write your own primitive transforms.]Once you know that primitive transforms will always receive all three parameters -- expression, state, and data -- it makes things possible that wouldn't be otherwise. For instance, consider that for binary expressions, these two transforms are equivalent. Can you see why?[table Two Equivalent Transforms  [[Without [^proto::fold<>]][With [^proto::fold<>]]]  [[``StringCopy(    proto::_right  , StringCopy(proto::_left, proto::_state, proto::_data)  , proto::_data)``][``proto::fold<_, proto::_state, StringCopy>``]]][endsect][/====================================================][section:canned_transforms Proto's Built-In Transforms][/====================================================][def _N_ [~N]][def _G_ [~G]][def _G0_ [~G0]][def _G1_ [~G1]][def _CT_ [~CT]][def _OT_ [~OT]][def _ET_ [~ET]][def _ST_ [~ST]][def _FT_ [~FT]]Primitive transforms are the building blocks for more interesting composite transforms. Proto defines a bunch of generally useful primitive transforms. They are summarized below.[variablelist [[_value_pt_]      [Given a terminal expression, return the value of the terminal.]] [[_child_c_pt_]      [Given a non-terminal expression, `proto::_child_c<_N_>` returns the _N_-th        child.]] [[_child_pt_]      [A synonym for `proto::_child_c<0>`.]] [[_left_pt_]      [A synonym for `proto::_child_c<0>`.]] [[_right_pt_]      [A synonym for `proto::_child_c<1>`.]] [[_expr_pt_]      [Returns the current expression unmodified.]] [[_state_pt_]      [Returns the current state unmodified.]] [[_data_pt_]      [Returns the current data unmodified.]] [[_call_pt_]      [For a given callable transform `_CT_`, `proto::call<_CT_>` turns the        callable transform into a primitive transform. This is useful for        disambiguating callable transforms from object transforms, and also for        working around compiler bugs with nested function types.]] [[_make_pt_]      [For a given object transform `_OT_`, `proto::make<_OT_>` turns the        object transform into a primitive transform. This is useful for        disambiguating object transforms from callable transforms, and also for        working around compiler bugs with nested function types.]] [[_default_pt_]      [Given a grammar _G_, `proto::_default<_G_>` evaluates the current node        according to the standard C++ meaning of the operation the node represents.       For instance, if the current node is a binary plus node, the two children        will both be evaluated according to `_G_` and the results will be added and       returned. The return type is deduced with the help of the Boost.Typeof        library.]] [[_fold_pt_]      [Given three transforms `_ET_`, `_ST_`, and `_FT_`,        `proto::fold<_ET_, _ST_, _FT_>` first evaluates `_ET_` to obtain a Fusion        sequence and `_ST_` to obtain an initial state for the fold, and then        evaluates `_FT_` for each element in the sequence to generate the next        state from the previous.]] [[_reverse_fold_pt_]      [Like _fold_pt_, except the elements in the Fusion sequence are iterated in        reverse order.]] [[_fold_tree_pt_]      [Like `proto::fold<_ET_, _ST_, _FT_>`, except that the result of the `_ET_`        transform is treated as an expression tree that is /flattened/ to generate        the sequence to be folded. Flattening an expression tree causes child nodes        with the same tag type as the parent to be put into sequence. For instance,        `a >> b >> c` would be flattened to the sequence \[`a`, `b`, `c`\], and this        is the sequence that would be folded.]] [[_reverse_fold_tree_pt_]      [Like _fold_tree_pt_, except that the flattened sequence is iterated in        reverse order.]] [[_lazy_pt_]      [A combination of _make_pt_ and _call_pt_ that is useful when the nature of        the transform depends on the expression, state and/or data parameters.        `proto::lazy<R(A0,A1...An)>` first evaluates `proto::make<R()>` to compute a        callable type `R2`. Then, it evaluates `proto::call<R2(A0,A1...An)>`.]]][/============================================][heading All Grammars Are Primitive Transforms][/============================================]In addition to the above primitive transforms, all of Proto's grammar elements are also primitive transforms. Their behaviors are described below.[variablelist [[_wild_]      [Return the current expression unmodified.]] [[_or_]      [For the specified set of alternate sub-grammars, find the one that matches        the given expression and apply its associated transform.]] [[_and_]      [For the given set of sub-grammars, take the /last/ sub-grammar and apply its        associated transform.]] [[_not_]      [Return the current expression unmodified.]] [[_if_]      [Given three transforms, evaluate the first and treat the result as a        compile-time Boolean value. If it is true, evaluate the second transform.        Otherwise, evaluate the third.]] [[_switch_]      [As with _or_, find the sub-grammar that matches the given expression and        apply its associated transform.]] [[_terminal_]      [Return the current terminal expression unmodified.]] [[_plus_, _nary_expr_, et. al.]      [A Proto grammar that matches a non-terminal such as       `proto::plus<_G0_, _G1_>`, when used as a primitive transform, creates a new        plus node where the left child is transformed according to `_G0_` and the        right child with `_G1_`.]]][/=================================][heading The Pass-Through Transform][/=================================]Note the primitive transform associated with grammar elements such as _plus_ described above. They possess a so-called /pass-through/ transform. The pass-through transform accepts an expression of a certain tag type (say, `proto::tag::plus`) and creates a new expression of the same tag type, where each child expression is transformed according to the corresponding child grammar of the pass-through transform. So for instance this grammar ...    proto::function< X, proto::vararg<Y> >... matches function expressions where the first child matches the `X` grammar and the rest match the `Y` grammar. When used as a transform, the above grammar will create a new function expression where the first child is transformed according to `X` and the rest are transformed according to `Y`.The following class templates in Proto can be used as grammars with pass-through transforms:[table Class Templates With Pass-Through Transforms    [[Templates with Pass-Through Transforms]]    [[`proto::unary_plus<>`]]    [[`proto::negate<>`]]    [[`proto::dereference<>`]]    [[`proto::complement<>`]]    [[`proto::address_of<>`]]    [[`proto::logical_not<>`]]    [[`proto::pre_inc<>`]]    [[`proto::pre_dec<>`]]    [[`proto::post_inc<>`]]    [[`proto::post_dec<>`]]    [[`proto::shift_left<>`]]    [[`proto::shift_right<>`]]    [[`proto::multiplies<>`]]    [[`proto::divides<>`]]    [[`proto::modulus<>`]]    [[`proto::plus<>`]]    [[`proto::minus<>`]]    [[`proto::less<>`]]    [[`proto::greater<>`]]    [[`proto::less_equal<>`]]    [[`proto::greater_equal<>`]]    [[`proto::equal_to<>`]]    [[`proto::not_equal_to<>`]]    [[`proto::logical_or<>`]]    [[`proto::logical_and<>`]]    [[`proto::bitwise_and<>`]]    [[`proto::bitwise_or<>`]]    [[`proto::bitwise_xor<>`]]    [[`proto::comma<>`]]    [[`proto::mem_ptr<>`]]    [[`proto::assign<>`]]    [[`proto::shift_left_assign<>`]]    [[`proto::shift_right_assign<>`]]    [[`proto::multiplies_assign<>`]]    [[`proto::divides_assign<>`]]    [[`proto::modulus_assign<>`]]    [[`proto::plus_assign<>`]]    [[`proto::minus_assign<>`]]    [[`proto::bitwise_and_assign<>`]]    [[`proto::bitwise_or_assign<>`]]    [[`proto::bitwise_xor_assign<>`]]    [[`proto::subscript<>`]]    [[`proto::if_else_<>`]]    [[`proto::function<>`]]    [[`proto::unary_expr<>`]]    [[`proto::binary_expr<>`]]    [[`proto::nary_expr<>`]]][/=====================================================][heading The Many Roles of Proto Operator Metafunctions][/=====================================================]We've seen templates such as _terminal_, _plus_ and _nary_expr_ fill many roles. They are metafunction that generate expression types. They are grammars that match expression types. And they are primitive transforms. The following code samples show examples of each.[*As Metafunctions ...]    // proto::terminal<> and proto::plus<> are metafunctions    // that generate expression types:    typedef proto::terminal<int>::type int_;    typedef proto::plus<int_, int_>::type plus_;    int_ i = {42}, j = {24};    plus_ p = {i, j};[*As Grammars ...]    // proto::terminal<> and proto::plus<> are grammars that    // match expression types    struct Int : proto::terminal<int> {};    struct Plus : proto::plus<Int, Int> {};    BOOST_MPL_ASSERT(( 

⌨️ 快捷键说明

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