File: operator.qbk

package info (click to toggle)
boost1.74 1.74.0-9
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 464,084 kB
  • sloc: cpp: 3,338,324; xml: 131,293; python: 33,088; ansic: 14,336; asm: 4,034; sh: 3,351; makefile: 1,193; perl: 1,036; yacc: 478; php: 212; ruby: 102; lisp: 24; sql: 13; csh: 6
file content (87 lines) | stat: -rw-r--r-- 3,241 bytes parent folder | download | duplicates (12)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
[/==============================================================================
    Copyright (C) 2001-2010 Joel de Guzman
    Copyright (C) 2001-2005 Dan Marsden
    Copyright (C) 2001-2010 Thomas Heller

    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)
===============================================================================/]

[section Lazy Operators]

You can use the usual set of operators to form expressions. Examples:

    arg1 * arg1
    ref(x) = arg1 + ref(z)
    arg1 = arg2 + (3 * arg3)
    ref(x) = arg1[arg2] // assuming arg1 is indexable and arg2 is a valid index

Note the expression: `3 * arg3`. This expression is actually a short-hand
equivalent to: `val(3) * arg3`. In most cases, like above, you can get away with
it. But in some cases, you will have to explicitly wrap your values in `val`.
Rules of thumb:

* In a binary expression (e.g. `3 * arg3`), at least one of the operands must be
  a phoenix primitive or expression.
* In a unary expression (e.g. `arg1++`), the single operand must be a phoenix
  primitive or expression.

If these basic rules are not followed, the result is either an error, or is
immediately evaluated. Some examples:

    ref(x) = 123    // lazy
    x = 123         // immediate

    ref(x)[0]       // lazy
    x[0]            // immediate

    ref(x)[ref(i)]  // lazy
    ref(x)[i]       // lazy (equivalent to ref(x)[val(i)])
    x[ref(i)]       // illegal (x is not a phoenix primitive or expression)
    ref(x[ref(i)])  // illegal (x is not a phoenix primitive or expression)

Why are the last two expression illegal? Although `operator[]` looks as
much like a binary operator as `operator=` above it; the difference is
that the former must be a member (i.e. `x` must have an `operator[]`
that takes a phoenix primitive or expression as its argument). This will
most likely not be the case.

[blurb __tip__ Learn more about operators [link phoenix.modules.operator here.]]

[heading First Practical Example]

We've covered enough ground to present a real world example. We want to find the
first odd number in an STL container. Normally we use a functor (function
object) or a function pointer and pass that in to STL's `find_if` generic
function:

Write a function:

    bool
    is_odd(int arg1)
    {
        return arg1 % 2 == 1;
    }

Pass a pointer to the function to STL's `find_if` algorithm:

    std::find_if(c.begin(), c.end(), &is_odd)

Using Phoenix, the same can be achieved directly with a one-liner:

    std::find_if(c.begin(), c.end(), arg1 % 2 == 1)

The expression `arg1 % 2 == 1` automagically creates a functor with the expected
behavior. In FP, this unnamed function is called a lambda function. Unlike the
function pointer version, which is monomorphic (expects and works only with a
fixed type int argument), the Phoenix version is fully polymorphic and works
with any container (of ints, of longs, of bignum, etc.) as long as its elements
can handle the `arg1 % 2 == 1` expression.

(See [@../../example/find_if.cpp find_if.cpp])

[blurb __tip__ ...[*That's it, we're done]. Well if you wish to know a little bit
more, read on...]

[endsect]