240 lines
7.1 KiB
Plaintext
240 lines
7.1 KiB
Plaintext
[/==============================================================================
|
|
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 Core]
|
|
|
|
Actors are composed to create more complex actors in a tree-like hierarchy. The
|
|
primitives are atomic entities that are like the leaves in the tree. Phoenix is
|
|
extensible. New primitives can be added anytime. Right out of the box, there are
|
|
only a few primitives, these are all defined in the Core module.
|
|
|
|
This section shall deal with these preset primitives.
|
|
|
|
[section Values]
|
|
|
|
|
|
#include <boost/phoenix/core/value.hpp>
|
|
|
|
Whenever we see a constant in a partially applied function, an
|
|
|
|
expression::value<T>::type
|
|
|
|
(where T is the type of the constant) is automatically created for
|
|
us. For instance:
|
|
|
|
add(arg1, 6)
|
|
|
|
Passing a second argument, `6`, an `expression::value<T>::type` is implicitly created
|
|
behind the scenes. This is also equivalent to `add(arg1, val(6))`.
|
|
|
|
val(v)
|
|
|
|
generates an `expression::value<T>::type` where `T` is the type of `v`. In most
|
|
cases, there's no need to explicitly use `val`, but, as we'll see later on,
|
|
there are situations where this is unavoidable.
|
|
|
|
[h2 Evaluating a Value]
|
|
|
|
Like arguments, values are also actors. As such, values can be evaluated.
|
|
Invoking a value gives the value's identity. Example:
|
|
|
|
cout << val(3)() << val("Hello World")();
|
|
|
|
prints out "3 Hello World".
|
|
|
|
[endsect]
|
|
|
|
[section References]
|
|
|
|
#include <boost/phoenix/core/reference.hpp>
|
|
|
|
Values are immutable constants. Attempting to modify a value will result in a
|
|
compile time error. When we want the function to modify the parameter, we use a
|
|
reference instead. For instance, imagine a lazy function `add_assign`:
|
|
|
|
void add_assign(T& x, T y) { x += y; } // pseudo code
|
|
|
|
Here, we want the first function argument, x, to be mutable. Obviously, we
|
|
cannot write:
|
|
|
|
add_assign(1, 2) // error first argument is immutable
|
|
|
|
In C++, we can pass in a reference to a variable as the first argument in our
|
|
example above. Yet, by default, the library forces arguments passed to partially
|
|
applied functions to be immutable values (see [link phoenix.modules.core.values
|
|
Values]). To achieve our intent, we use:
|
|
|
|
expression::reference<T>::type
|
|
|
|
This is similar to `expression::value<T>::type` before but instead holds a reference to a
|
|
variable.
|
|
|
|
We normally don't instantiate `expression::reference<T>::type` objects directly. Instead we
|
|
use:
|
|
|
|
ref(v)
|
|
|
|
For example (where `i` is an `int` variable):
|
|
|
|
add_assign(ref(i), 2)
|
|
|
|
[heading Evaluating a Reference]
|
|
|
|
References are actors. Hence, references can be evaluated. Such invocation gives
|
|
the reference's identity. Example:
|
|
|
|
int i = 3;
|
|
char const* s = "Hello World";
|
|
cout << ref(i)() << ref(s)();
|
|
|
|
prints out "3 Hello World"
|
|
|
|
|
|
[heading Constant References]
|
|
|
|
Another free function
|
|
|
|
cref(cv)
|
|
|
|
may also be used. `cref(cv)` creates an
|
|
`expression::reference<T const>::type` object. This is similar to `expression::value<T>::type` but
|
|
when the data to be passed as argument to a function is heavy and expensive to
|
|
copy by value, the `cref(cv)` offers a lighter alternative.
|
|
|
|
[endsect]
|
|
|
|
[section Arguments]
|
|
|
|
#include <boost/phoenix/core/argument.hpp>
|
|
|
|
We use an instance of:
|
|
|
|
expression::argument<N>::type
|
|
|
|
to represent the Nth function argument. The argument placeholder acts as an
|
|
imaginary data-bin where a function argument will be placed.
|
|
|
|
[heading Predefined Arguments]
|
|
|
|
There are a few predefined instances of `expression::argument<N>::type` named
|
|
`arg1`..`argN`, and its __bll__ counterpart `_1`..`_N`. (where N is a predefined
|
|
maximum).
|
|
|
|
Here are some sample preset definitions of `arg1`..`argN`
|
|
|
|
namespace placeholders
|
|
{
|
|
expression::argument<1>::type const arg1 = {};
|
|
expression::argument<2>::type const arg2 = {};
|
|
expression::argument<3>::type const arg3 = {};
|
|
}
|
|
|
|
and its __bll__ `_1`..`_N` style counterparts:
|
|
|
|
|
|
namespace placeholders
|
|
{
|
|
expression::argument<1>::type const _1 = {};
|
|
expression::argument<2>::type const _2 = {};
|
|
expression::argument<3>::type const _3 = {};
|
|
}
|
|
|
|
[note You can set `BOOST_PHOENIX_ARG_LIMIT`, the predefined maximum
|
|
placeholder index. By default, `BOOST_PHOENIX_ARG_LIMIT` is set to `BOOST_PHOENIX_LIMIT`
|
|
(See [link phoenix.actor Actor]).]
|
|
|
|
[heading User Defined Arguments]
|
|
|
|
When appropriate, you can define your own `argument` names. For example:
|
|
|
|
expression::argument<1>::type x; // note one based index
|
|
|
|
`x` may now be used as a parameter to a lazy function:
|
|
|
|
add(x, 6)
|
|
|
|
which is equivalent to:
|
|
|
|
add(arg1, 6)
|
|
|
|
[/note
|
|
When dealing with argument placeholders the question arises whether you can call
|
|
member functions on an `argument` actor.
|
|
|
|
This is possible by supplying a custom `actor` which has a member
|
|
generator function. See [link phoenix.advanced_topics.extending_actors Extending Actors]
|
|
for more details.
|
|
]
|
|
|
|
[heading Evaluating an Argument]
|
|
|
|
An argument, when evaluated, selects the Nth argument from the those passed
|
|
in by the client.
|
|
|
|
For example:
|
|
|
|
char c = 'A';
|
|
int i = 123;
|
|
const char* s = "Hello World";
|
|
|
|
cout << arg1(c) << endl; // Get the 1st argument: c
|
|
cout << arg1(i, s) << endl; // Get the 1st argument: i
|
|
cout << arg2(i, s) << endl; // Get the 2nd argument: s
|
|
|
|
will print out:
|
|
|
|
A
|
|
123
|
|
Hello World
|
|
|
|
[heading Extra Arguments]
|
|
|
|
In C and C++, a function can have extra arguments that are not at all used by
|
|
the function body itself. These extra arguments are simply ignored.
|
|
|
|
Phoenix also allows extra arguments to be passed. For example, recall our
|
|
original `add` function:
|
|
|
|
add(arg1, arg2)
|
|
|
|
We know now that partially applying this function results to a function that
|
|
expects 2 arguments. However, the library is a bit more lenient and allows the
|
|
caller to supply more arguments than is actually required. Thus, `add` actually
|
|
allows 2 /or more/ arguments. For instance, with:
|
|
|
|
add(arg1, arg2)(x, y, z)
|
|
|
|
the third argument `z` is ignored. Taking this further, in-between arguments are
|
|
also ignored. Example:
|
|
|
|
add(arg1, arg5)(a, b, c, d, e)
|
|
|
|
Here, arguments b, c, and d are ignored. The function `add` takes in the first
|
|
argument (`arg1`) and the fifth argument (`arg5`).
|
|
|
|
[note There are a few reasons why enforcing strict arity is not
|
|
desirable. A case in point is the callback function. Typical callback functions
|
|
provide more information than is actually needed. Lambda functions are often
|
|
used as callbacks.]
|
|
|
|
[endsect]
|
|
|
|
[section Nothing]
|
|
|
|
#include <boost/phoenix/core/nothing.hpp>
|
|
|
|
Finally, the `expression::null<mpl::void_>::type` does nothing; (a "bum", if you will :-) ).
|
|
There's a sole `expression::null<mpl::void_>::type` instance named "nothing". This actor is
|
|
actually useful in situations where we don't want to do anything. (See
|
|
[link phoenix.modules.statement.for_statement for_ Statement] for example).
|
|
|
|
[endsect]
|
|
|
|
[endsect]
|