
Hicham Mouline wrote:
Eric Niebler wrote:
Hicham Mouline wrote:
The complication comes in my case from the fact that the grammar is not stand alone type but an inner-type.
Why does that make a difference?
Rather I meant to say that the grammar "constdef_rhs_grammar" is an inner type of
template<typename Expr> struct constant_wrapper { ... };
And so in struct contants_domain : proto::domain< proto::pod_generator<constant_wrapper>, constant_wrapper<Expr>::constdef_rhs_grammar > {}; obviously wouldn't work.
It wasn't the grammar parameter I was objecting to. In the code you posted, you had a bogus generator: struct contants_domain : proto::domain< proto::generator<contants_domain> // THIS IS WRONG , calculator_grammar > {}; Now you've changed the generator to proto::pod_generator<constant_wrapper> which looks better. As for the grammar parameter, just leave it unspecified. In your constant_wrapper::operator= overload, you have a compile-time assertion to catch invalid assignment expressions. That's sufficient. For any particular Proto-based DSEL, there needs to be a 1-to-1-to-1 correspondence between: 1) The domain type, 2) The generator for the domain, which adds extra domain-specific functionality to expressions within the domain, and 3) The grammar for the domain, which is used to disable Proto's operator overloads that would create invalid expressions. You seem to be creating a domain for constant expressions. Will these constants be appearing within expressions of another domain? If so, I suspect you'll run into trouble. I suggest you create 1 domain for your DSEL, with 1 generator and 1 grammar. You can actually have multiple expression wrappers within the same domain with a cleverly defined generator. The only requirement on the generator is that it is a polymorphic function object that accepts expressions and returns (possibly wrapped) expressions. A grammar with transforms fits this definition. Check out the following: #include <boost/proto/proto.hpp> namespace proto = boost::proto; using proto::_; template<class E> struct wrap1; template<class E> struct wrap2; // You can use a grammar with transforms as a generator struct Generator : proto::or_< proto::when< proto::assign<_,_> , proto::pod_generator<wrap1>(_) > , proto::otherwise< proto::pod_generator<wrap2>(_) > > {}; struct Domain : proto::domain<Generator> {}; // Note, wrap1 and wrap2 are both in the same domain template<class E> struct wrap1 { BOOST_PROTO_EXTENDS(E, wrap1, Domain) }; template<class E> struct wrap2 { BOOST_PROTO_EXTENDS(E, wrap2, Domain) }; typedef wrap1<proto::terminal<int>::type> I; typedef wrap2<proto::terminal<int>::type> J; I const i = {{1}}; J const j = {{2}}; int main() { wrap1< proto::assign<I const &, J const &>::type > x = (i = j); // OK, i and j are in the same domain wrap2< proto::plus<I const &, J const &>::type > y = (i + j); // OK, i and j are in the same domain } In main(), notice that an assignment creates a wrap1 object, whereas an addition creates a wrap2 object. Both are in the same domain. In short, you should be able to get along with just 1 domain for your DSEL, and it'll make things *much* simpler. HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com