Why compilation fails when a template parameter name matches an inner class name?
Asked Answered
H

0

6

Following compiles perfectly fine:

struct MyClass {
  template<typename SameName>
  void foo (SameName* p);
};
struct SameName {};

template<class SameName>
void MyClass::foo (SameName* p) {}

However, if we enclose MyClass and SameName inside some class Outer then the template function defined outside, fails to compile.

struct Outer {
  /* paste here `MyClass` & `SameName` from above */
};

template<class SameName>
void Outer::MyClass::foo (SameName* p) {}  // <--- error here
//   ^^^^^

The g++ (03-14) error is weird:

error: prototype for ‘void Outer::MyClass::foo(Outer::SameName*)’ does not match any in class ‘Outer::MyClass’
 void Outer::MyClass::foo (SameName* p) {}
      ^~~~~
templateClassMethod.cpp:6:10: error: candidate is: template<class SameName> void Outer::MyClass::foo(SameName*)
     void foo (SameName* p);

The clang (03-14) error is less intuitive:

error: out-of-line definition of 'foo' does not match any declaration in 'Outer::MyClass'
void Outer::MyClass::foo (SameName* p) {}

Question:

  • Is this a language/compiler bug or an expected behaviour?
  • If expected, then why is the choice for template type's name being restricted for inner classes?

[Note: Actually I had many template parameters, and incidentally one of them matched the inner class name, by chance. It took me 1 hour to figure out. The error generated in that complex scenario was totally misleading.]

Heilbronn answered 22/12, 2016 at 9:46 Comment(6)
The cause of the error is that when looking up the name SameName used in the function parameter type, name lookup finds the member name ::Outer::SameName instead of the template parameter name SameName. However, I cannot seem to pinpoint the standard wording which would indicate correct lookup results here.Leaseback
@Angew, that is fine, had it been uniformly applied. However, for the classes which are not inside another class, this issue doesn't happen. Just compile the same code by replacing struct Outer with namespace Outer and things work fine. What should be the reason for the standard, to restrict the choice of template type names for inner classes (2nd query)?Heilbronn
Lookup rules for names from enclosing class and names from containing namespace are spelled out independently in the standard, so it's not inherently "inconsistent." The standard treats these two situations separately.Leaseback
Compare core issues 458/459. This area is messy.Sequence
i'm sorry for my previous answer, it was wrong. That seems to be a bug (according to this). also i have asked similar question on that.Magnificence
@GreenTree, No problem for posting an answer. I was not anyways aware of it. :-) If you get an answer or if I get something here then feel free to mark it as duplicate.Heilbronn

© 2022 - 2024 — McMap. All rights reserved.