Boost logo

Proto :

Subject: Re: [proto] vararg + fold
From: Eric Niebler (eric_at_[hidden])
Date: 2010-07-21 11:22:39


On 7/21/2010 9:02 AM, Christophe Henry wrote:
>>> template <class T>
>>> struct make_vector
>>> {
>>> typedef boost::mpl::vector<T> type;
>>> };
>>>
>>> struct B
>>> : proto::or_<
>>> proto::when <
>>> A,
>>> make_vector<A(proto::_)>()
>
>> You could simply use mpl::vector1<A(proto::_)>() and not bother with
>> make_vector.
>
> Indeed. I tried with mpl::vector and it doesn't compile but vector1
> does. Interesting.

I should also point out that mpl::vector1<A>() is the same as above. It
works with vector1 and not vector because mpl::vector's arity greatly
exceeds the maximum template arity that proto's transforms are built to
handle by default.

>> If A is a grammar as implied above, you can simplify the function to:
>>
>> mpl::push_back<proto::_state, A>()
>>
>> The current element in the sequence will be operated on by default.
>
> This doesn't compile but I need to have a closer look, it could be
> another problem.
> A is actually a proto::switch on 2 cases, terminals and preincrement
> (for the moment).
>
>
>> Whoops! Your grammar doesn't handle expressions that aren't comma
>> expressions. Before passing an expr to a grammar, first try asserting
>> that it matches the grammar.
>
> This is done but not shown in the example. I use the grammar inside a function:
> ...
> foo(Expr)
> {
> BOOST_MPL_ASSERT((proto::matches<Expr, B>));
> ...
> }
>
>
>> If it doesn't evaluating the grammar's
>> transform with the expr is a precondition violation. In this case, the
>> grammar check is ignored and the fold_tree is executed against whatever
>> expression you passed in. That will fold the tree on the top-most node
>> type; e.g. if it's tag::plus, you'll fold on plus.
>
> Ah yes I learned this one the hard way last night ;-)
>
>
>>> So I suppose that at least the first part of when is wrong.
>>> Any idea how to make it work?
>>
>> Depends on what you're trying to do. What should happen when you pass
>> something that isn't a comma expression?
>
> I call the grammar inside a function which asserts if proto::match rejects it.
> What I now have is a grammar which should parse a variable number of A
> expressions:
> ++_1
> ++_1, ++_1
> ++_1, ++_1, ++_1
> etc.
>
> So I don't think comma<A,A> can possibly work, this would cover only
> (++_1,++_1) , right?

I was getting my A's and B's mixed up, and you're getting your A's and
trees mixed up. What you want is:

struct B
  : or_<
        when< comma< B, B >, fold_tree<..as before..> >
      , when< A, mpl::vector1<A>() >
>
{};

An expression like (A0,A1,A2) builds a binary tree like:

comma---+
| |
comma A2
| |
A0 A1

Use display_expr to see. fold_tree first flattens the tree on the type
of the top-most node (comma), resulting the the sequence (A0,A1,A2) and
then calls fold on that.

Incidentally, for the "state" parameter to fold_tree, you're using
mpl::vector<>(). That works by luck. Because of the template arity
thing, proto can't pull vector<> apart to check for nested transforms
(but there are none anyway). You'll better express your intent with
mpl::vector0<>().

HTH,

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com

Proto list run by eric at boostpro.com