1

This seems to work:

template<class A> struct S {
    template<class B> friend S<B> f(B);
};

template<class B> S<B> f(B) {return S<B>{};}

int main() {
    f(5);
}

http://ideone.com/lApGTi

OK, so let’s do a seemingly purely cosmetic change and move the definition of f to the body of the struct:

template<class A> struct S {
    template<class B> friend S<B> f(B) {return S<B>{};}
};

int main() {
    f(5);
}

Suddenly compilation starts failing:

prog.cpp: In function ‘int main()’:
prog.cpp:6:5: error: ‘f’ was not declared in this scope
  f(5);
     ^

http://ideone.com/ImsQtJ

Why does a template friend function need to be defined outside of the class to work in this snippet?

Is there any trick that would allow function f to be defined within the body of the class definition?

1 Answers1

0

When you implement the friend function inline, inside the class, its declaration is not visible outside the class without argument-dependent lookup.

That is useful only when the friend function is used by the class or any of its nested classes.

That problem exists with regular classes also, not just class templates. The following is a problem too.

struct S {
   friend S f(int) {return S{};}
};

int main() {
   f(5);
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • In that case, why can we define **inline**, for example, `friend ostream &operator << (ostream &os, myClass const &mc)` and then use it: `cout << myClass{}`? This operator should be invisible outside of `myClass` if defined inline, yet we can still use it? http://ideone.com/P7eNbl –  Mar 17 '17 at 20:25
  • That works due to ADL. – R Sahu Mar 17 '17 at 20:26
  • /me reads whatever ADL is :) –  Mar 17 '17 at 20:28
  • @gaazkam, you can read about ADL at http://en.cppreference.com/w/cpp/language/adl. – R Sahu Mar 17 '17 at 20:30
  • @gaazkam I suggest you read the duplicate I posted. It is very complete. – SergeyA Mar 17 '17 at 20:33