2016-04-07 6 views
8

Dieser Code mit Klirren3.7.1 (ohne Diagnose), aber nicht mit GCC5.3.0 (live example) kompiliert:Template Freundschaft Fehler mit GCC Kompilierung aber nicht mit Klirren

#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(); 
} 

Fehlermeldung des GCC ist die folgende:

main.cpp:13:16: error: specialization of 'A' after instantiation friend struct A;

Welches ist richtig und warum? Ist es ein Bug von GCC/Clang?

Antwort

4

Scheint ein alter g ++ Bug (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52625) zu sein.

Berichtet und nie korrigiert, wenn ich richtig verstehe,

+1

Sie richtig sind. Darüber hinaus scheint gcc viele [Probleme mit Freunden] zu haben (https://gcc.gnu.org/bugzilla/showdependencytree.cgi?id=65608&hide_resolved=1). – akakatak

3

Ich denke, das ist gcc's Bug.

Eine Vorlage Freundschaftsklasse Deklaration ist nur eine Deklaration, keine Definition. Die Deklaration der Klassenvorlage ist erlaubt, es sei denn, sie hat einen anderen Klassenschlüssel (siehe N4527 14.5.1.4).

Spezialisierung oder Instanziierung kann zweimal oder öfter erfolgen. Explizite Spezialisierung kann nur einmal vorkommen (N4527 14.7.3.6).

Dann ist die Diagnose von gcc seltsam, weil es keine explizite Spezialisierung gibt.

0

Wir haben einige Template-Namensauflösung Chancen haben:

struct Crtp : A<Crtp> { 
    A x; // A refers to A<Crtp> 
}; 

Jetzt sind die Dinge klar:

template<typename T> friend struct A; 

bezieht:

template<typename T> friend struct A<Crtp>; 

was ist ... ja, teilweise Spezialisierung (wirklich schwierig).

Also GCC ist hier richtig.

Was Sie wirklich brauchen, zu tun ist:

struct Crtp : A<Crtp> { 
friend struct A; 
private: 
    void implementation() { std::cout << "implementation()\n"; } 
};