I am trying to implement function call operators with Boost.Proto but cannot seem to figure out either how to set the expression trees up or how to evaluate them properly.  The code below is simplified from the “checked calculator” example in the Proto documentation to focus on implementing a single identity function resulting from the Proto expression ‘identity(_1)’.  The program prints the following

function(
    terminal(9identity_)
  , terminal(0)
)
result=0 [ expect 3 ]

so I think the expression tree is correct.  (I am, however, uncertain why the placeholder is reported as ‘terminal(0)’.)

When the expression tree is evaluated with IdentityGrammar transform, the result is 0 not 3 as I would have expected if the placeholder value was used.

The Proto documentation seems very thorough (at least after study), but is thin on the use of functions like this and is not helping me figure  out the solution.  I welcome any help that will point out the flaw(s) in this code for either setting up the expression tree or getting it evaluated correctly by calling the identity function with the correct argument.

Thanks for your help.

Cheers,
Brook


#include <boost/proto/proto.hpp>
#include <boost/mpl/int.hpp>
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/container/generation/make_vector.hpp>

namespace mpl = boost::mpl;
namespace proto = boost::proto;
namespace fusion = boost::fusion;

template<typename I> struct placeholder : I {};

struct identity : proto::callable
{
  typedef int result_type;
  int operator()(int a) const
  {
    return a;
  }
};

struct identity_ {};

struct IdentityGrammar
  : proto::or_<
    proto::when<
      proto::terminal<placeholder<proto::_>>
      , proto::functional::at(proto::_state, proto::_value)
      >
  , proto::when<proto::terminal<identity_>, proto::_void>
  , proto::when<
      proto::function<IdentityGrammar, proto::terminal<proto::_>>
      , proto::and_<
 IdentityGrammar(proto::_child1)
 , identity(proto::_value(proto::_child1))
 >
      >
  >
{};

template<typename Expr>
struct identity_expr;

struct identity_domain
  : proto::domain<proto::pod_generator<identity_expr>, IdentityGrammar>
{};

template<typename Expr>
struct identity_expr
{
  BOOST_PROTO_EXTENDS(Expr, identity_expr<Expr>, identity_domain)
};

identity_expr<proto::terminal<identity_>::type> const identity = {{}};
identity_expr<proto::terminal<placeholder<mpl::int_<0> > >::type> _1;

int main()
{
  auto expr = identity(_1);
  proto::display_expr(expr);
  int result = IdentityGrammar()(expr,fusion::make_vector(3));
  std::cout << "result=" << result << " [ expect 3 ]" << std::endl;
  return 0;
}