This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115f. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-12-06
[Voted into the WP at the June, 2008 meeting.]
13.8 [temp.res] paragraphs 2 and 4 read,
A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.
If a specialization of a template is instantiated for a set of template-arguments such that the qualified-id prefixed by typename does not denote a type, the specialization is ill-formed.
It is not clear whether this is intended to, or is sufficient to, render a specialization ill-formed if a dependent qualified-id that is not prefixed by typename actually does denote a type. For example,
int i; template <class T> void f() { T::x * i; // declaration or multiplication!? } struct Foo { typedef int x; }; struct Bar { static int const x = 5; }; int main() { f<Bar>(); // multiplication f<Foo>(); // declaration! }
I think that the specialization for Foo should be ill-formed.
Proposed resolution (February, 2008):
Add the following after 13.8 [temp.res] paragraph 5:
If, for a given set of template arguments, a specialization of a template is instantiated that refers to a qualified-id that denotes a type, and the nested-name-specifier of the qualified-id depends on a template parameter, the qualified-id shall either be prefixed by typename or shall be used in a context in which it implicitly names a type as described above. [Example:
template <class T> void f(int i) { T::x * i; // T::x must not be a type } struct Foo { typedef int x; }; struct Bar { static int const x = 5; }; int main() { f<Bar>(1); // OK f<Foo>(1); // error: Foo::x is a type }—end example]