|
Boost Users : |
Subject: Re: [Boost-users] [proto] defining function call operators on expressions
From: Eric Niebler (eric_at_[hidden])
Date: 2010-02-28 23:18:45
On 3/1/2010 2:21 PM, Manjunath Kudlur wrote:
> Yeah, got it. I realise now that the passing a domain to make_expr
> wraps all the components of the expression also with the corresponding
> expression class. What I am unable to figure out it how to wrap only
> the final expression I want with program_expr. In this case I want to
> wrap expr<tag::function, vararg<terminal<Var> > > with program_expr.
> Is there an example I can look at that does something similar? Or is
> this the wrong way to look at the problem? Basically, I want to add
> the function call operator to my expressions, but only to expressions
> of certain forms. My thinking is, if I only wrap expressions of that
> certain form with my expression class, I should be OK, no?
>
Ah, you want a different expression interface based on the structure of
the expression being wrapped. There's a straightforward way to do that,
but it's not obvious. See the program below.
#include <boost/utility/result_of.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/proto/proto.hpp>
namespace proto = boost::proto;
using proto::_;
// This wrapper is for function expressions
template<typename Expr>
struct function_expr;
// This wrapper is for all other expressions
template<typename Expr>
struct program_expr;
struct function_call
: proto::function< proto::vararg< proto::terminal<_> > >
{};
struct program_generator
: proto::or_<
// Wrap function expressions in function_expr
proto::when<
function_call
// pod_generator is a function object and
// so can be used to make this callable
// transform
, proto::pod_generator<function_expr>(_)
>
// Wrap all other expressions in program_expr
, proto::otherwise<
proto::pod_generator<program_expr>(_)
>
>
{};
// A program_generator satisfies the requirement for
// a proto generator because it is a unary function
// object, albeit a rather complicated one.
struct program_domain
: proto::domain< program_generator >
{};
template<typename Expr>
struct function_expr
{
BOOST_PROTO_BASIC_EXTENDS(Expr, function_expr<Expr>, program_domain)
BOOST_PROTO_EXTENDS_FUNCTION()
void I_am_a_function() const {}
};
template<typename Expr>
struct program_expr
{
BOOST_PROTO_BASIC_EXTENDS(Expr, program_expr<Expr>, program_domain)
BOOST_PROTO_EXTENDS_FUNCTION()
void I_am_not_a_function() const {}
};
program_expr<proto::terminal<int>::type> i = {{1}};
program_expr<proto::terminal<int>::type> j = {{2}};
int main()
{
i.I_am_not_a_function();
(i + j).I_am_not_a_function();
i(j).I_am_a_function();
(i(j) + j(i)).I_am_not_a_function();
}
-- Eric Niebler BoostPro Computing http://www.boostpro.com
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