Reputation: 12757
This code compiles with clang 3.7.1 (with no diagnostic) but fails with GCC 5.3.0 (live example):
#include <iostream>
template<typename T>
struct A {
void foo()
{
static_cast<T*>(this)->implementation();
}
};
struct Crtp : A<Crtp> {
template<typename T>
friend struct A;
private:
void implementation() { std::cout << "implementation()\n"; }
};
int main()
{
Crtp c;
c.foo();
}
GCC's error message is the following:
main.cpp:13:16: error: specialization of 'A' after instantiation friend struct A;
Which one is right and why? Is it a bug of GCC / clang?
Upvotes: 8
Views: 163
Reputation: 595
I think this is gcc's bug.
A template friend class declaration is only a declaration, not a definition. Redeclaration of class template is allowed unless it has different class-key (see N4527 14.5.1.4).
Specialization or instantiation can occur twice or more. Explicit specialization can occur only once(N4527 14.7.3.6).
Then, gcc's diagnostics is odd because there is no explicit specialization.
Upvotes: 3
Reputation: 6989
We do have some template name resolution odds:
struct Crtp : A<Crtp> {
A x; // A refers to A<Crtp>
};
Now things are clear:
template<typename T> friend struct A;
refers to:
template<typename T> friend struct A<Crtp>;
which is... yeah, partial specialization (really tricky one).
So GCC is correct here.
What do you really need is:
struct Crtp : A<Crtp> {
friend struct A;
private:
void implementation() { std::cout << "implementation()\n"; }
};
Upvotes: 0
Reputation: 66200
Seems to be an old g++ bug (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52625).
Reported and never corrected, if I understand correctly,
Upvotes: 4