Reputation: 8759
The following piece of code fails to compile properly with both G++ and Clang++, whatever the C++ standard required (98, 11, 14):
$ cat foo.cc
template <typename T>
struct foo
{
friend void bar(){}
};
int main()
{
foo<int> fi;
foo<char> fc;
}
for instance:
$ clang++-mp-3.7 -std=c++14 foo.cc
foo.cc:4:15: error: redefinition of 'bar'
friend void bar(){}
^
foo.cc:10:13: note: in instantiation of template class 'foo<char>' requested here
foo<char> fc;
^
foo.cc:4:15: note: previous definition is here
friend void bar(){}
^
1 error generated.
I know I can avoid this problem by putting the definition (not declaration) of bar
out of foo
, I'm not asking for a workaround. Rather, I would like to understand what's going on. So I have two questions:
First, I don't see where in the standard this behavior is documented, or implied. I doubt than both G++ and Clang++ would get this wrong, so I expected that it is documented/implied somewhere.
Second, what's the point of this behavior? There is value in defining friends inside the class (see for instance Is there any difference if we define friend function inside or outside of class), so what is the value of keeping this behavior. I mean, shouldn't the standard accept the behavior as one (I) would expect?
Upvotes: 3
Views: 222
Reputation: 5680
For each T
a new class is created. So foo<int>
is one class and foo<char>
is another.
If you take your example and unwind it, it will look like this:
struct foo_int
{
friend void bar() {}
};
struct foo_char
{
friend void bar() {}
};
int main()
{
foo_int fi;
foo_char fc;
}
Through the friend
keyword you are defining a static global (namespace scope) function named bar
.
And as you see here you are doing it twice.
Upvotes: 3