Document number: | 03-0111/N1528 |
Date: | September 19, 2003 |
Author: | John Spicer, Edison Design Group |
jhs@edg.com |
This is a revision to issue 96 in the core issues list and a follow-up to an earlier discussion of the issue in N1231.
In my original reflector posting on this subject I recommended that
the standard be changed to require that the template
keyword be followed by a template-id (i.e., a name followed by
a template-argument-list).
The following example gives the rationale for this recommendation.
The template
keyword is only supposed to provide syntactic
disambiguation, not affect name lookup (just as is the case with the
typename
keyword). This results in the surprising behavior
that call #2 does not call the template function.
template
keyword
is needed in the default argument to indicate that T::C
is
a template, just as typename
would be required if
T::C
were a type.
template
keyword without a following template-id
.
If we allow the template keyword to be followed by a name without a template-argument-list we must then decide what it means for functions in such cases (i.e., we must resolve the issue illustrated by the first example above). For classes it is not an issue (if the name is followed by a template-argument-list, it refers to a specialization of the class template, if not, it refers to the class template itself).
There are two possible interpretations that I can think of:
template
keyword is applied to an overload set
containing both template and non-templates, the non-templates are ignored.
In other words, it is treated as if the name were followed by an
empty template-argument-list (i.e., <>
).
template
keyword is followed by a name that does
not have a template-argument-list, the name must refer to
a class template and be used in a context in which a class template
is valid (i.e., the example above would be ill-formed).
Existing practice seems to favor #2. The Microsoft, g++, and EDG compilers
all accept a.template f<>(t)
, and all reject
a.template f(t)
.
When this was last discussed, a few issues were raised:
template
keyword interact with
using-declarations.
template
when naming a
dependent template template argument?
The first issue has now been dealt with by issue #109 (template
is not permitted before the final component of a qualified-name in
a using-declaration).
As for the second issue, the template
keyword is not
required in order for syntactic purposes, so in theory it would be
possible to not require its use when naming a dependent template template
argument. However, the same statement could be made about certain uses
of typename
that are not strictly required.
I've personally gone back and forth on the issue of permitting
template
in a class member access that does not include a
template argument list. My summary of the strongest arguments on both
sides are:
typename
and template
to make their use
simpler. It would be nice if we could allow template
in places where it is not required to make life easier on less sophisticated
users.
template
were to affect the set of names considered
by overload resolution in a reference like "p->template f()
",
the keyword would have subtle semantic effects, something that we've
been avoiding for both typename
and template
.
What looks like an advantage to the user (being able to liberally use
template
) can actually have surprising semantic consequences.
In other words, both of these would be valid:
While I would like to make use of template
easier for users,
I think the cost of understanding the subtle semantic impact outweighs
any advantages.
Consequently, the recommendation of this paper is:
If the template
keyword is followed by a name that does
not have a template-argument-list, the name must refer to
a class template and be used in a context in which a class template
is valid, otherwise the program is ill-formed.