From reading the documentation, I understand that expressions and objects that are wrapped in proto::terminal<> are held by reference. In the following code, in the "assign" grammar, I match proto::terminal<Var<proto::_> > and call _assign on proto::_value. As expected, a reference to the object held in the terminal gets passed to the callable transform, and I can assign some value to it.
template<typename VT> struct Var { VT value; void assign(const VT v) { value = v; } }; struct _assign : proto::callable { typedef void result_type; template<typename VT> result_type operator()(Var<VT> &var) const { var.assign(20); } }; struct assign : proto::or_< proto::when<proto::terminal<Var<proto::_> >, _assign(proto::_value)>
{};
typedef proto::terminal<Var<int> >::type int32_; int main() { int32_ a,b,c; assign()(a); std::cout << proto::value(a).value << std::endl; } Now, I add the following rules to assign grammar : struct assign : proto::or_< proto::when<proto::terminal<Var<proto::_> >, _assign(proto::_value)>, proto::when<proto::assign<proto::terminal<Var<proto::_> >, proto::literal<proto::_> >, _assign(proto::_value(proto::_left), proto::_value(proto::_right))>, proto::when<proto::function<proto::terminal<Var<proto::_> >, proto::literal<proto::_> >, _assign(proto::_value(proto::_left), proto::_value(proto::_right))>
{};
and the following operator() overload to _assign : template<typename VT> result_type operator()(Var<VT> &var, const VT val) const { var.assign(val); } I can merrily call assign()(a=10) and I get the expected behaviour. But when I call assign()(a(20)), I get a compilation error saying that there is no match for operator()(const Var<int> &, const int &). Why is that when I call proto::_value(proto::_left) on a proto::function expression, a *const* reference gets passed to the transform? Did I miss some part of the documentation where this is explained? Manjunath