This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 110c. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2023-02-07


215. Template parameters are not allowed in nested-name-specifiers

Section: 13.2  [temp.param]     Status: CD1     Submitter: Martin von Loewis     Date: 13 Mar 2000

[Voted into WP at April, 2007 meeting.]

According to 13.2 [temp.param] paragraph 3, the following fragment is ill-formed:

    template <class T>
    class X{
      friend void T::foo();
    };

In the friend declaration, the T:: part is a nested-name-specifier (9.3 [dcl.decl] paragraph 4), and T must be a class-name or a namespace-name (_N4567_.5.1.1 [expr.prim.general] paragraph 7). However, according to 13.2 [temp.param] paragraph 3, it is only a type-name. The fragment should be well-formed, and instantiations of the template allowed as long as the actual template argument is a class which provides a function member foo. As a result of this defect, any usage of template parameters in nested names is ill-formed, e.g., in the example of 13.8 [temp.res] paragraph 2.

Notes from 04/00 meeting:

The discussion at the meeting revealed a self-contradiction in the current IS in the description of nested-name-specifiers. According to the grammar in _N4567_.5.1.1 [expr.prim.general] paragraph 7, the components of a nested-name-specifier must be either class-names or namespace-names, i.e., the constraint is syntactic rather than semantic. On the other hand, 6.5.5 [basic.lookup.qual] paragraph 1 describes a semantic constraint: only object, function, and enumerator names are ignored in the lookup for the component, and the program is ill-formed if the lookup finds anything other than a class-name or namespace-name. It was generally agreed that the syntactic constraint should be eliminated, i.e., that the grammar ought to be changed not to use class-or-namespace-name.

A related point is the explicit prohibition of use of template parameters in elaborated-type-specifiers in 9.2.9.4 [dcl.type.elab] paragraph 2. This rule was the result of an explicit Committee decision and should not be unintentionally voided by the resolution of this issue.

Proposed resolution (04/01):

Change _N4567_.5.1.1 [expr.prim.general] paragraph 7 and A.5 [gram.expr] from

to

This resolution depends on the resolutions for issues 245 (to change the name lookup rules in elaborated-type-specifiers to include all type-names) and 283 (to categorize template type-parameters as type-names).

Notes from 10/01 meeting:

There was some sentiment for going with simply identifier in front of the "::", and stronger sentiment for going with something with a more descriptive name if possible. See also issue 180.

Notes from April 2003 meeting:

This was partly resolved by the changes for issue 125. However, we also need to add a semantic check in 6.5.5 [basic.lookup.qual] to allow T::foo and we need to reword the first sentence of 6.5.5 [basic.lookup.qual].

Proposed resolution (October, 2004):

Change 6.5.5 [basic.lookup.qual] paragraph 1 as follows:

The name of a class or namespace member can be referred to after the :: scope resolution operator (_N4567_.5.1.1 [expr.prim.general]) applied to a nested-name-specifier that nominates its class or namespace. During the lookup for a name preceding the :: scope resolution operator, object, function, and enumerator names are ignored. If the name found is not a class-name (Clause 11 [class]) or namespace-name (9.8.2 [namespace.def]) does not designate a class or namespace, the program is ill-formed. [...]

Notes from the April, 2005 meeting:

The 10/2004 resolution does not take into account the fact that template type parameters do not designate class types in the context of the template definition. Further drafting is required.

Proposed resolution (April, 2006):

Change 6.5.5 [basic.lookup.qual] paragraph 1 as follows:

The name of a class or namespace member can be referred to after the :: scope resolution operator (_N4567_.5.1.1 [expr.prim.general]) applied to a nested-name-specifier that nominates its class or namespace. During the lookup for a name preceding the :: scope resolution operator, object, function, and enumerator names are ignored. If the name found is not a class-name (Clause 11 [class]) or namespace-name (9.8.2 [namespace.def]) does not designate a namespace or a class or dependent type, the program is ill-formed. [...]