$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [Boost-users] proto: analytical-only math functions
From: Eric Niebler (eric_at_[hidden])
Date: 2009-03-06 13:02:58
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