
Larry Evans wrote:
On 03/02/08 19:39, Eric Niebler wrote: [snip]
Your problem distills down to:
typedef terminal<x> GX; // grammar for x typedef GX::type EX; // expression for x
typedef shift_right<GX, GX> SRGX; // grammar for x>>x typedef SRGX::type SREX; // OOPS!
You then try to use SREX as a valid expression type, and it is not. It should be:
typedef shift_right<EX, EX>::type SREX;
The difference is that in the first case, you're creating the type of a right shift expression where the operands are grammars. You really want the operands to be expression types.
HTH,
Yes, thanks. I had actually concluded that, but then thought, in that case, the shift_right template arguments can be either grammar types or expression types and, depending on which they are, the nested type may or may not make sense.
That's not the case. In binary_expr<A,B,C>::type, if B and C are expressions, ::type is an expression. If they are grammars, ::type is a grammar. It is merely a matter of convenience that you can leave off the ::type when you want to use binary_expr<> as a grammar.
That kinda bothered me because it was confusing. Someone reading the code would have to realize this to avoid confusion.
Here's actually part of what I had written before sent my post:
b) operator expressions
For each operator grammar instance (see above), O_inst, there's the corresponding type of expressions which match that grammar. For example, if:
typedef O < T0 , T1 , ... , Tn > O_inst; typedef O < T0::type , T1::type , ... , Tn::type >::type O_expr;
then:
matches<O_expr,O_inst>
OOPS. This doesn't make sense either because in one instance the the template args are grammar types and in the 2nd they're expressiont types. Looking at traits.hpp shows:
There's lots of reasons why this generalization is untrue. You can't, in general, construct an expression type from a grammar type. First of all, these are recursive data structures. There is no operation you can apply at the root of such a type that achieves the effect you're after. But more importantly, most grammar elements (e.g., and_, or_, not_, if_, switch_, etc.) don't even have a nested ::type.
template<typename Tag, typename T, typename U> struct binary_expr : pass_through<binary_expr<Tag, T, U> > { BOOST_PROTO_NOT_CALLABLE() typedef proto::expr<Tag, args2<T, U> > type; typedef type proto_base_expr; typedef Tag proto_tag; typedef T proto_arg0; typedef U proto_arg1; };
so the subexpression types are grammar types?
Grammars or expressions, whichever. (Note: in the latest download, binary_expr looks different but behaves the same.)
I'd be more comfortable if the validity of the nested type didn't depend on particular type of the template parameter.
It doesn't. -- Eric Niebler Boost Consulting www.boost-consulting.com