This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-12-19
[Voted into WP at August, 2010 meeting.]
The list of cases in 13.8.2 [temp.local] about when a template parameter is hidden seems to be incomplete.
Consider
// example-1 struct S { int C; template<class> void f(); }; template<class C> void S::f() { C c; // #1 }
Someone asked whether line #1 is well-formed and I responded "no" based on my understanding of the rules in 14.6.1. After a second looking, I've realized that the above case is currently missing from the list.
The list in 14.6.1 covers cases like
// example-2 template<class T> struct S { int C; void f(); }; template<class C> void S<C>::f() { C c; // ERROR: 'C' is 'S::C' not the template parameter }or
// example-3 struct A { int C; } template<class C> struct S : A { C c; // ERROR: 'C' is 'A::C', not the template parameter };But the case of a 'member template' is missing. I believe it should follow the same rule as above. The reason is this.
In the case listed in 14.6.1 (having to do with members of classes), the "algorithm" seems to be this:
I believe that any rule, coherent with 14.6.1/5 and 14.6.1/7, for covering the cases of member templates (example-1) will be described by the above "algorithm".
Am I missing something?
[1] of course, the standard text does not formally speak of "template parameter scope", but we all know that the template parameters "live" somewhere. I'm using that terminology to designate the declarative region of the template parameters.
Mike Miller: I have a somewhat different perspective on this question. I think your example-1 is fundamentally different from your example-2 and example-3. Looking, for instance, at your example-2, I see four nested scopes:
namespace scope template scope (where the parameter is) class S scope S::f() block scope
Naturally, S::C hides the template parameter C. The same is true of your example-3, with three scopes:
namespace scope template scope class S scope (includes 10.2 base class lookup)
Again, it's clear that the C inherited from A hides the template parameter in the containing scope.
The scopes I see in your example-1, however, are different:
namespace scope struct S scope template scope (where the parameter is) S::f() block scope
Here it seems clear to me that the template parameter hides the class member.
It might help to look at the case where the function template is defined inline in the class:
struct S { int C; template<class C> int f() { C c; // #1 } };
It would be pretty strange, I think, if the #1 C were the member and not the template parameter. It would also be odd if the name lookup were different between an inline definition and an out-of-line definition.
See also issue 459.
Notes from the March 2004 meeting:
Basically, the standard is okay. We think Gaby's desired cases like #1 should be ill-formed.
There is a wording problem in 13.8.2 [temp.local] paragraph 7. It says:
In the definition of a member of a class template that appears outside of the class template definition, the name of a member of this template hides the name of a template-parameter.
It should say "hides the name of a template-parameter of the class template (but not a template-parameter of the member, if the member is itself a template)" or words to that effect.
Proposed resolution (February, 2010):
Change 13.8.2 [temp.local] paragraph 8 as follows:
In the definition of a member of a class template that appears outside of the class template definition, the name of a member of
thisthe class template hides the name of a template-parameter of any enclosing class templates (but not a template-parameter of the member, if the member is a class or function template). [Example:template<class T> struct A { struct B { /* ... */ }; typedef void C; void f(); template<class U> void g(U); }; template<class B> void A<B>::f() { B b; // A's B, not the template parameter } template<class B> template<class C> void A<B>::g(C) { B b; // A's B, not the template parameter C c; // the template parameter C, not A's C }