Boost logo

Boost Users :

Subject: [Boost-users] [proto] defining function call operators on expressions
From: Manjunath Kudlur (keveman_at_[hidden])
Date: 2010-02-28 03:17:08


I am trying to define operator()(...) for my expressions. I want to be
able to form expression of the form Program_(a,b) and call Program_(a,
b)(10,20). Here, 'a' and 'b' are terminals and I have a mechanism
shown in the code below that somehow gets the type suitable for the
parameter position. Suppose 'a' is terminal<Var<int> >, I want the
first parameter position in Program_(a,b) (pos1, pos2) to be of the
type 'int'.
typename boost::result_of<call_param_type<M>(const Expr &)>::type
gives me that type for the Mth argument in the expression of the form
Program_(a1,a2,...). Now, I am trying to use this to define
operator()(...) in my program_expr class. That doesn't seem to work.
However, if I define a separate function callfunc, that takes the
expression and the arguments, that seems to work. In the following
code, enabling the if 0'ed out code results in compilation errors. How
do I go about defining operator()(...) in my program_expr class with
the above property?

Thanks,
Manjunath

#include <boost/proto/proto.hpp>
#include <boost/proto/proto_typeof.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/assert.hpp>

#include <iostream>
#include <sstream>
#include <string>

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

unsigned int ids;

template<typename VT>
struct Var {
  unsigned int id;
  Var() {
    id = ++ids;
  }
};

typedef proto::terminal<Var<int> >::type int32_;
typedef proto::terminal<Var<float> >::type float_;

struct program_ {};

template<class E> struct program_expr;

struct program_domain
  : proto::domain<proto::pod_generator<program_expr> > {
};

struct _var_type
  : proto::callable {

  template<typename Sig>
  struct result;

  template<typename This, typename T>
  struct result<This(const Var<T> &)> {
    typedef T type;
  };
};

struct var_type
  : proto::or_<
    proto::when<proto::terminal<Var<proto::_> >,
    _var_type(proto::_value)>
> {};

template<int N>
struct call_param_type
  : proto::or_<
    proto::when<
    proto::function<
    proto::terminal<program_>,
    proto::vararg<proto::terminal<Var<proto::_> > > >,
    var_type(proto::_child_c<N+1>)>
> {};

template <typename Expr>
struct program_expr {
  BOOST_PROTO_BASIC_EXTENDS(Expr, program_expr<Expr>, program_domain);
  BOOST_PROTO_EXTENDS_SUBSCRIPT();

  typedef void result_type;

#if 0
  result_type operator()(typename
boost::result_of<call_param_type<0>(const Expr &)>::type x) {
    std::cout << "program with one arg\n";
  }
  result_type operator()(typename
boost::result_of<call_param_type<0>(const Expr &)>::type x,
                         typename
boost::result_of<call_param_type<1>(const Expr &)>::type y) {
    std::cout << "program with two args\n";
  }
#endif
};

template<typename Expr>
void callfunc(const Expr &e,
              typename boost::result_of<call_param_type<0>(const Expr
&)>::type x)
{
  std::cout << "program with one arg\n";
}

template<typename Expr>
void callfunc(const Expr &e,
              typename boost::result_of<call_param_type<0>(const Expr
&)>::type x,
              typename boost::result_of<call_param_type<1>(const Expr
&)>::type y)
{
  std::cout << "program with two args\n";
}

template<typename A0>
typename proto::result_of::make_expr<proto::tag::function
, program_domain
, program_
, A0 const &>::type const
Program_(A0 const &a0)
{
  return proto::make_expr<proto::tag::function, program_domain>(
         program_(),
         boost::ref(a0));
}

template<typename A0, typename A1>
typename proto::result_of::make_expr<proto::tag::function
, program_domain
, program_
, A0 const &
, A1 const &>::type const
Program_(A0 const &a0, A1 const &a1)
{
  return proto::make_expr<proto::tag::function, program_domain>(
    program_(),
    boost::ref(a0),
    boost::ref(a1));
}

int main()
{
  int32_ a,b,c;

  callfunc(Program_(a, b), 10, 20);
#if 0
  Program_(a, b)(10, 20);
#endif
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net