Paolo M
Paolo M

Reputation: 12757

Template friendship error compilation with GCC but not with clang

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

Answers (3)

akakatak
akakatak

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

Konstantin Vladimirov
Konstantin Vladimirov

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

max66
max66

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

Related Questions