|
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