Actor 是整个 Phoenix 的核心,几乎所有的组件事实上都是 Actor。但是这个处于中心地位的组件,其实是一个很简单的 concept:Actor 就是一个functor,它接受0~N个参数。
template <typename Eval> struct actor : Eval { return_type operator()() const; template <typename T0> return_type operator()(T0& _0) const; template <typename T0, typename T1> return_type operator()(T0& _0, T1& _1) const; //... };
actor 的模板参数,Eval,给 actor 提供了特例化的行为。下面我们会看到,其余的 Phoenix 组件是如何在 actor 的基础上,建立起一座优美的建筑的。
#include <boost/spirit/home/phoenix/core/argument.hpp>
Phoenix 的 Arguments 就是占位符,它们就像一个个数据“桶”,我们可以把数据放在里面,当作函数的参数来传递。它们的类型其实是:
actor<argument<N> >
N 代表第 N 个参数。Phoenix 已经预定义了几个参数占位符:
actor<argument<0> > const arg1 = argument<0>();
actor<argument<1> > const arg2 = argument<1>();
actor<argument<2> > const arg3 = argument<2>();
......
#include <boost/spirit/home/phoenix/core/value.hpp>
Phoenix 的 value 是用来包装常数的,当我们把一个常数6传递给一个 lazy function 的时候,它实际是包装在一个 actor<value<int> > 对象里面。所有 value 的类型都是
actor<value<T> >
其中 T 自然是常数的类型,在第一篇的例子中,已经使用过类似 val(3) 这样的表达式,实际上 val 就会产生一个 actor<value<T> > 对象。
#include <boost/spirit/home/phoenix/core/reference.hpp>
Value 是包装常量的,如果要包装变量的引用,就要用到 reference,不用说,它们的类型是
actor<reference<T> >
T 仍然是变量的类型。这个模块在前面没有详细的例子,请看下面代码:
#include <iostream> #include <vector> #include <algorithm> #include <boost/spirit/home/phoenix/core.hpp> #include <boost/spirit/home/phoenix/operator.hpp> using namespace std; using namespace boost::phoenix; using namespace boost::phoenix::arg_names; int main() { vector<int> v(10); int i = 1; std::generate(v.begin(), v.end(), ref(i)++); std::for_each(v.begin(), v.end(), cout << arg1 << " "); return 0; }
输出:
1 2 3 4 5 6 7 8 9 10
在 std::generate(v.begin(), v.end(), ref(i)++) 这一行,每一次 ref(i)++ 被调用时,它除了返回 i 的当前引用,还真正对 i 的引用做自增操作,这样 i 的值会不断增加,从而把个等差数列填入 v。