10

Here is the code:

struct foo {
  template<typename T = void>
  friend foo f() { return {}; }
};

int main() {
  auto x = f(); // clang++ can't find it, g++ can.
}

clang++ 3.4 gives:

fni2.cpp:8:12: error: use of undeclared identifier 'f'
  auto x = f(); // clang++ can't find it, g++ can.
           ^
1 error generated.

g++ 4.9.0 compiles it, but I don't think it should have. This is a related question, but there was no definitive answer. Section 15.4.2/2,4 discuss this, but neither of them say anything to suggest that friend function templates defined in-class should have different visibility from non-template friend functions defined in-class.

This is of academic interest to me only, though it did arise from a question by someone else who may have had an actual use case.

It looks like a g++ bug to me.

Community
  • 1
  • 1
kec
  • 2,099
  • 11
  • 17
  • looks like g++ is wrong, [scope of inline friend functions](http://stackoverflow.com/questions/8207633/whats-the-scope-of-inline-friend-functions) – yngccc May 04 '14 at 03:20
  • Yes. I also think that g++ is wrong. Just wanted to see if anyone else is reading those paragraphs in the standard differently from me, or if there was some paragraph in the standard that I missed. – kec May 04 '14 at 03:31
  • I saw this used by some people to replace methods with functions. they use class as a scope. – yngccc May 04 '14 at 03:39
  • @yngum It's a valid trick, but you have to re-declare the function [template] outside the `class` definition. (Better style would be to use a `namespace` and `using` declaration, though.) – Potatoswatter May 04 '14 at 11:48
  • @yngum: What's the motivation for that? Why not use a namespace? One possibility that comes to mind would be to leverage partial specialization. – kec May 04 '14 at 12:50
  • @kec I don't see any reason, it is mostly a style, some people like to package data and functions on the data together. I mostly just declare functions after a struct without namespace, I don't like methods. – yngccc May 04 '14 at 18:35

1 Answers1

7

Yes, this is an error. I'm surprised it's finding the function. Apparently GCC fails entirely to hide function templates.

This C++03 example also compiles, so it could be a regression:

struct foo {
  template<typename T >
  friend void f( T ) { }

};

int main() {
  f( 3 ); // clang++ can't find it, g++ can.
}
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • It's also (apparently) broken without a default template arg. (I'll edit to make that clear.) If not a template, then g++ can't find it as expected. – kec May 04 '14 at 03:44
  • @user3521733 No worries, I already tried it and updated the answer. – Potatoswatter May 04 '14 at 03:45