
Eric Niebler <eric@boost-consulting.com> writes:
Tough questions. You've touched on a weakness of proto. I hope to make improvements in this area after BoostCon ...
Maurizio Vitale wrote:
Suppose I needed a new tag for representing some high-level concept that I do not want to express in terms of C++ operators [it could be a get_bit(N) operation that has very different implementation when for my numbers the unserlyining implementation is a builtin type or a GMP big int]
Here's my code for adding a binary operator my_plus:
struct my_plus {};
template<typename Left, typename Right> proto::expr<my_plus, proto::args2<proto::ref_<Left>, proto::ref_<Right> > > const make_my_plus_expr(Left& left, Right& right) { typedef proto::expr<my_plus, proto::args2<proto::ref_<Left>, proto::ref_<Right> > > expr_type; expr_type that={left,right}; return proto::generate<typename Left::domain, expr_type>::make (that); }
Questions:
- is the above the right way, or is there some friendlier interface?
There's another way to achieve the same effect by just declaring a nullary my_plus and then let the proto machinery do its job by mean of operator()(). In this case the result would be: (function (terminal my_plus expr0 expr1)) The grammar can take care that only binary applications are allowed [my_plus could even declare its arity so that this can be done in a generic way]. What are pro/cons of the two solutions? Compile-time evaluation should be the same (albeit probably more expensive at compile-time). For evaluation in contexts I think the matching becomes more difficult to express (haven't tired it, maybe it doesn't even work) in that you need to overload on function_tag and then use boost::{dis,en}able_if to control the overload set. Run-time cost should be the same. Eric, are the two approach equivalent? or you see particular advantages for one of them? Regards, Maurizio