
On 03/03/08 00:21, Eric Niebler wrote:
Larry Evans wrote:
If the template arguments are grammars then shift_right<L,R>::type is not an expression type.
Correct, it's a grammar type.
AFAICT, it's of no use.
That's not true. The fact that shift_right<L,R>::type creates expressions when L and R are expressions, and grammars when L and R are grammars,
Are you saying shift_right<L,R>::type is a grammar when L and R are grammars or did you mean shift_right<L,R> is a grammar when L and R are grammars? If the latter, then what is shift_right<L,R>::type when L and R are grammars? More specifically, is there any use (for example, in code you or anyone else has written) of shift_right<L,R>::type where L and R are grammars? If not, then, shift_right<L,R>::type, where L and R are grammars, obviously has no use. If yes, could you please post such code or give a link to it so that I can better understand your meaning?
is an important symmetry that is leveraged extensively within Proto. And what would the alternative be? To have two classes, expression::shift_right<> that generates expression types, and grammar::shift_right<> that creates grammar rules? This would surely be worse for users.
Could you explain why it would be worse? I can see that one downside of the two-class solution would be requiring the user to remember which of two namespaces to use under the two different circumstances. The upside is that, although the user would be required to remember two namespaces, he would only have to remember one in any particular circumstance: 1) circumstance 1: grammars: use grammar::shift_right<> with only grammar arguments. 2) circumstance 2: expressions: use expression::shift_right<>:: with only expression arguments. IOW, use different namespaces but the same template name for different circumstances. The different namespace name reinforces different circumstances so that the user doesn't inadvertently use the wrong template name. OTOH, for the current one-class solution, the user has to remember the "kind" of template argument to use depends on whether or not he intends to use the nested type or just the grammar itself: 1) circumstance 1: grammars: use proto::shift_right<> with only grammar arguments. 2) circumstance 2: expressions: use proto::shift_right<>::type with only expression arguments. Note, there is no clue in the proto::shift_right name as to which "kind" of template argument to use. This lack of any clues lead me to mistakenly use grammar arguments to produce a an expression type, and I don't remember seeing any documentation warning against this. In summary, it's just too easy for the user (in particular a novice user) to make the wrong assumption about what kind of argument to supply to the "grammar" template. As a side note: an alternative to using different namespaces in the two-class solution would be using the same template name but with an extra template parameter used to signal the intention. For example: enum grammar_or_expr { is_grammar , is_expr }; template<grammar_or_expr GorE, class Left, class Right> shift_right; Shift_right could then be specialized on is_expr to define the nested type, and on the is_grammar to *not* define the nested type. Of course that's not much different than the two-namespace approach; so, I'm not sure which would be better.
Why have two when one works just as well?
The one-class solution is likely to cause users to stumble (see my last paragraph).
Or are you suggesting something else?
I'm suggesting either the two class solution or (my 2nd choice) a prominent warning in the documentation of grammar classes explaining that the nested type is only useful when the actual template arguments are expression types. I believe this is important because I stumbled over this and had to decipher the compiler error messages before I could figure out that L and R in shift_right<L,R>::type had to be expression types. I believe it's likely that, without either such prominent warning documentation or a two-class template solution, other users (at least novice users) would also stumble like I did. -regards, Larry