简体   繁体   中英

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?

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,

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.

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"; }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM