123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- [/==============================================================================
- 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]
|