2016-09-26 11 views
25

, neden bu ince derliyor:C++ 'da, neden başka bir sınıfın şablon türünü kullanarak bir şablon sınıf üyesi işlevine arkadaşlık etmek mümkün değildir? Başka bir deyişle

template<typename Type> 
class A{ 
    public: 
    void f(); 
}; 

class B{ 
    friend void A<int>::f(); 
}; 

template<> 
void A<int>::f(){ 
    B* var = new B(); 
} 

bu değil iken:

template<typename Type> 
class A{ 
    public: 
    void f(); 
}; 

template<typename Type> // B is now a templated class 
class B{ 
    friend void A<Type>::f(); // Friending is done using B templated type 
}; 

template<> 
void A<int>::f(){ 
    B<int>* var = new B<int>(); // var is now declared using int as its templated type 
} 

ikinci kod parçacığı, derleyici (gcc 6.2, hiçbir özel bayraklar) için diyor ki:

main.cpp: In instantiation of ‘class B<int>’: 
main.cpp:14:28: required from here 
main.cpp:9:15: error: prototype for ‘void A<int>::f()’ does not match any in class ‘A<int>’ 
    friend void A<Type>::f(); 
       ^~~~~~~ 
main.cpp:13:6: error: candidate is: void A<Type>::f() [with Type = int] 
void A<int>::f(){ 

Anladığım kadarıyla, ikinci kod snippet'inde, derleyici bildirimde bulunulduğunda, derleyici B sınıfı bildirimini ayrıştırmalı, arkadaşta kullanılan Türü değiştir int tarafından beyan ve her şey iyi çalışmalıdır. Neyi kaçırıyorum?

DÜZENLEME: aşağıdaki yorum ikinci kod parçacığı uzmanlaşmış olmadan clang ve Visual C++ 2015

+5

sadece FYI. clang – Hayt

+1

ile derlemek gibi görünüyor Ayrıca burada deneyebilirsiniz gibi Visual C++ 2015 ile derler: http://webcompiler.cloudapp.net/ – Tunichtgut

+0

Hem clang 3.8 ve gcc 6.1.0 çalışır [Demo] (http: // coliru.stacked-crooked.com/a/14434a24d4688733) – Jarod42

cevap

3

A<int>::f()'da kullanılmadan önce B<int>'un açık bir örneği bu sorunu giderir. GCC'nin A<int>::f() tanımında B<int> örtük bir örneğini denediğini varsayalım. Ama A<int>::f()'un tanımı bitmedi ve GCC 'arkadaşlık beyanını' kaybediyor. Derleyici problemi gibi görünüyor.

template<typename Type> 
class A 
{ 
public: 
    void f(); 
}; 

template<typename Type> // B is now a templated class 
class B 
{ 
    friend void A<Type>::f(); // Friending is done using B templated type 
}; 

template 
class B<int>; // <= explicit instantiation, that works 

template<> 
void A<int>::f() 
{ 
    B<int>* var = new B<int>(); 
} 
0

template class üye işlevini uzmanlaşmış ile düzgün derlemek görünüyor dikkat çekmişlerdir bütün template class sen olmayan uzmanlaşmak için izin verilen özel bir durumdur template üye işlevi, belki de GCC karışıktır ve nedenleri bilmiyorum, ancak bir şekildetemplate class üyesi olmayan uzmanlık için arkadaşlık bildiremezsiniz. Geçici çözüm, bunun çalışması için tüm class template'u uzmanlaştırmak olacaktır.

void A<int>::f(){ 
     B<int>* var = new B<int>(); 
     (void)(var); 
} 

Ama böyle hiçbir problem olmalı, Clang tam burada olduğunu düşünüyorum:

template class B için

void A<int>::f(){ 
     B* var = new B(); 
     (void)(var); 
} 

class B: için:

//class template A 
template<typename Type> 
class A{ 
    public: 
    void f(); 
}; 

//class A<int> 
template<> 
class A<int>{ 
    public: 
    void f(); 
}; 

Sonra A<int>::f tanımlamak arkadaş declarati üzerinde. Muhtemelen GCC'da bir hata.

İlgili konular