...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
The main concept is the Actor
.
An Actor
is a model of the
Polymorphic
Function Object concept (that can accept 0 to N arguments (where
N is a predefined maximum).
An Actor
contains a valid
Phoenix Expression, a call to one of the function call operator overloads,
starts the evaluation process.
Note | |
---|---|
You can set |
The actor
template class
models the Actor
concept:
template <typename Expr> struct actor { template <typename Sig> struct result; typename result_of::actor<Expr>::type operator()() const; template <typename T0> typename result_of::actor<Expr, T0 &>::type operator()(T0& _0) const; template <typename T0> typename result_of::actor<Expr, T0 const &>::type operator()(T0 const & _0) const; //... };
Table 1.9. Actor Concept Requirements
Expression |
Semantics |
---|---|
|
Function call operators to start the evaluation |
|
Result of the evaluation |
|
Result of the evaluation |
There are 2*N function call operators for 0 to N arguments (N == BOOST_PHOENIX_LIMIT
). The actor class accepts
the arguments and forwards the arguments to the default evaluation action.
Additionally, there exist function call operators accepting permutations
of const and non-const references. These operators are created for all N
<= BOOST_PHOENIX_PERFECT_FORWARD_LIMIT
(which defaults to 3).
Note | |
---|---|
Forwarding Function Problem
There is a known issue with current C++ called the "Forwarding
Function Problem". The problem is that given an arbitrary
function |
On an actor function call, before calling the evaluation function, the actor
created a context. This context consists
of an Environment
and an
Action
part. These contain
all information necessary to evaluate the given expression.
Table 1.10. Context Concept Requirements
Expression |
Semantics |
---|---|
|
Type of a Context |
|
A Context containing environment |
|
Type of the contained Environment |
|
The environment |
|
Type of the contained Actions |
|
The actions |
The Environment is a model of Random Access Sequence.
The arguments passed to the actor's function call operator are collected inside the Environment:
Other parts of the library (e.g. the scope module) extends the Environment
concept to hold other information
such as local variables, etc.
Actions is the part of Phoenix which are responsible for giving the actual expressions a specific behaviour. During the traversal of the Phoenix Expression Tree these actions are called whenever a specified rule in the grammar matches.
struct actions { template <typename Rule> struct when; };
The nested when
template
is required to be Proto
Primitive Transform. No worries, you don't have to learn Boost.Proto
just yet! Phoenix provides some wrappers to let you define simple actions
without the need to dive deep into proto.
Phoenix ships with a predefined default_actions
class that evaluates the expressions with C++ semantics:
struct default_actions { template <typename Rule, typename Dummy = void> struct when : proto::_default<meta_grammar> {}; };
For more information on how to use the default_actions class and how to attach custom actions to the evaluation process, see more on actions.
struct evaluator { template <typename Expr, typename Context> unspecified operator()(Expr &, Context &); }; evaluator const eval = {};
The evaluation of a Phoenix expression is started by a call to the function
call operator of evaluator
.
The evaluator is called by the actor
function operator overloads after the context is built up. For reference,
here is a typical actor::operator()
that accepts two arguments:
template <typename T0, typename T1> typename result_of::actor<Expr, T0 &, T1 &>::type operator()(T0 &t0, T1 &t1) const { fusion::vector2<T0 &, T1 &> env(t0, t1); return eval(*this, context(env, default_actions())); }
For reasons of symmetry to the family of actor::operator()
there is a special metafunction usable
for actor result type calculation named result_of::actor
.
This metafunction allows us to directly specify the types of the parameters
to be passed to the actor::operator()
function. Here's a typical actor_result
that accepts two arguments:
namespace result_of { template <typename Expr, typename T0, typename T1> struct actor { typedef fusion::vector2<T0, T1> env_tpe; typedef typename result_of::context<env_type, default_actions>::type ctx_type typedef typename boost::result_of<evaluator(Expr const&, ctx_type)>::type type; }; }