Document number:  03-0111/N1528
Date:  September 19, 2003
Author:  John Spicer, Edison Design Group
 jhs@edg.com

Syntactic Disambiguation Using the Template Keyword

Discussion

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.

struct A { void f(int); template <class T> void f(T); }; template <class T> void f(T t) { A a; a.template f<>(t); // #1 calls template a.template f(t); // #2 but does this call the template? } The counter example came up while we were implementing template template parameters. In this example, the 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 <class T> struct A {template <class T2> struct C {}; }; template <class T, template <class X> class TT = T::template C> struct B {}; In other words, there are cases where we need to permit the 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:

  1. When the 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., <>).
  2. 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 (i.e., the example above would be ill-formed).
Note that a name that refers to a class template (and not to a specialization of the class template) must be a template argument associated with a template template parameter, because there is no other context in which a template name without a template-argument-list is permitted).

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:

  1. How does the the template keyword interact with using-declarations.
  2. Is it really necessary to use 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.

Recommendations

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:

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.

End of document.