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

2025-04-13


398. Ambiguous wording on naming a type in deduction

Section: 13.10.3  [temp.deduct]     Status: CD1     Submitter: Daveed Vandevoorde     Date: 16 Jan 2003

[Voted into WP at March 2004 meeting.]

The following example (simplified from a posting to comp.lang.c++.moderated) is accepted by some compilers (e.g., EDG), but not by other (e.g., g++).

 struct S { static int const I = 42; }; template<int N> struct X {}; template<typename T> void f(X<T::I>*) {} template<typename T> void f(X<T::J>*) {} int main() { f<S>(0); } 

The wording in the standard that normally would cover this (third sub-bullet in 13.10.3 [temp.deduct] paragraph 2) says:

Attempting to use a type in the qualifier portion of a qualified name that names a type when that type does not contain the specified member, or if the specified member is not a type where a type is required.
(emphasis mine). If the phrase "that names a type" applies to "a qualified name," then the example is invalid. If it applies to "the qualifier portion," then it is valid (because the second candidate is simply discarded).

I suspect we want this example to work. Either way, I believe the sub-bullet deserves clarification.

Notes from April 2003 meeting:

We agreed that the example should be valid. The phrase "that names a type" applies to "the qualifier portion."

Proposed resolution (October 2003):

In 13.10.3 [temp.deduct], paragraph 2, bullet 3, sub-bullet 3, replace

Attempting to use a type in the qualifier portion of a qualified name that names a type when that type does not contain the specified member, or if the specified member is not a type where a type is required.

With

Attempting to use a type in a nested-name-specifier of a qualified-id when that type does not contain the specified member, or

[Example:

Replace the example that follows the above text with

 template <int I> struct X { }; template <template <class T> class> struct Z {}; template <class T> void f(typename T::Y*){} template <class T> void g(X<T::N>*){} template <class T> void h(Z<T::template TT>*){} struct A {}; struct B { int Y; }; struct C { typedef int N; }; struct D { typedef int TT; }; int main() { // Deduction fails in each of these cases: f<A>(0); // A does not contain a member Y f<B>(0); // The Y member of B is not a type g<C>(0); // The N member of C is not a nontype h<D>(0); // The TT member of D is not a template } 
]


close