Re: Inconsistent placement of the keywords 'typename' and 'template'
Seungbeom Kim wrote:
template <typename T1> struct test_type
{
typedef int type_name;
template <typename T2> static void template_func();
};
template <typename T> void call_test()
{
// ________
typename test_type<T>::type_name var;
// ________
test_type<T>::template template_func<int>();
}
So, 'typename' comes before the qualified name, while 'template'
intervenes into the qualified name, even though both of them serve the
same purpose of helping the compiler resolve the syntactic ambiguity.
Would anyone care to explain why we have this inconsistency?
Actually typename and template do not serve the same purpose in the
examples above. The typename keyword provides semantic information
about an identifier (whether the identifier names a type or an object),
but with or without a typename being present the compiler can interpret
the production on its own.
In the second example, the template keyword does resolve syntactic
ambiguity: the compiler needs help choose whether the < and > are part
of a template name or whether each one represents an operator in a
relative comparison expression (even if it is ill-formed).
Now to answer this type of question, the accurate but unhelpful answer
always is: the typename and template keywords appear where they do
because the C++ grammar says that's where they go. In that case, let's
find out what the grammar has to say for itself.
First the production for the typename declaration looks like this:
typename-specifier:
typename ::_opt nested-name-specifier identifier
So the structure is pretty straightforward: the keyword typename
appears on the far left, the identifier on the far right with a nested
name specifer (possibly preceded by a double colon) in between.
As it turns out the template key word appears with the the nested name
specifier production:
nested-name-specifier:
nested-name-specifier template_opt simple-template-id ::
From this production it is clear that a nested-name-specifier is
recursive, so any number of template keywords may be needed for each
nested layer.
We can try experimenting with alternate productions. For example:
::_opt nested-name-specifier typename identifier
could be argued is more consistent with the template example, but is
typename's new location an improvement over where it was?
For the nested name specifier, how about moving the template keyword to
the beginning:
template_opt nested-name-specifier simple-template-id ::
The programmer will just have to remember that the first template
keyword is paired with the last template id, the second template
keyword would go with the second-to last template, and so forth, moving
in toward the center from each direction. I think this revision would
work great as a practical joke, but would not go over well in this
case: C++ after all is not Perl.
Greg
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]