-1

Could you please advise why I am getting the error in the code below?

error: cannot define member function ‘Test<int>::Printer::Print’ within ‘Test<int>’

I am using gcc version 8.1.1 and compile the code as g++ -std=c++11.

Although, if I move the definition of function Print under the definition of struct Printer (i.e. making it inline implicitly), the compiler does not produce any error.

#include <iostream>

template <typename Type>
struct TestBase {

 struct Printer {
  template <typename T>
  void Print(const T& t) {
    std::cout << t << std::endl;
  }
 };

};

template <typename Type>
struct Test;

template<>
struct Test<int> : public TestBase<int> {

 struct Printer : public TestBase<int>::Printer {
  template <typename T>
  void Print(int i, const T& t);
 };

 template <typename T>
 void Printer::Print(int i, const T& t) {
  std::cout << i << t << std::endl;
 }

};

int main() {
  Test<int> t;
}

UPDATE:

Brian pointed out the exact reason why it is the case: "... A member function definition that appears outside of the class definition shall appear in a namespace scope enclosing the class definition..."

Brian not only answered the main question that started this topic but also an additional question that I asked in the comment to the accepted answer of him.

TruLa
  • 1,031
  • 11
  • 21
  • Read the error message carefully. The compiler is telling you the truth. If you want to know why, it's because that's specified by the C++ standard. – paddy Nov 15 '18 at 20:55
  • I think I understand the compiler's message but I don't understand which rule is violated. Could you please help me to point that out? – TruLa Nov 15 '18 at 20:58

1 Answers1

3

[class.mfct]/1, emphasis mine:

... A member function definition that appears outside of the class definition shall appear in a namespace scope enclosing the class definition. ...

An enclosing class scope is thus not an allowed location for the definition.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • Brian, thank you very much for such a prompt and precise answer. I have a suspicion that this might not be the end of a story. Let's move the member function `Print` definition inside the `struct Printer` definition and change the `main` function as `Test::Printer p; p.Print(3);`. I'll start getting the `no matching function for call to` error message. Is it somehow related to your answer? Is it because `void Print(const T& t)` is defined outside of the class definition? – TruLa Nov 15 '18 at 21:10
  • 1
    @TruLa This is because `Test::Printer::Print` takes two arguments and it *hides* `TestBase::Printer::Print`. See https://stackoverflow.com/questions/1896830/why-should-i-use-the-using-keyword-to-access-my-base-class-method – Brian Bi Nov 15 '18 at 21:16