2016-09-26 5 views
25

दूसरे शब्दों में, क्यों यह ठीक संकलित करता है:सी ++ में, क्यों नहीं यह संभव दोस्त के लिए एक टेम्पलेट वर्ग के सदस्य अन्य वर्ग की टेम्पलेट प्रकार का उपयोग समारोह है?

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

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

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

हालांकि यह नहीं करता है:

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 
} 

दूसरी कोड का टुकड़ा, संकलक (जीसीसी 6.2, कोई विशेष झंडे) के लिए कहते हैं:

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(){ 

जैसा कि मैं इसे समझता हूं, दूसरे कोड स्निपेट में, जब संकलक var घोषित करता है तो बी वर्ग घोषणा को पार्स करना चाहिए, दोस्त में इस्तेमाल किए गए प्रकार को प्रतिस्थापित करें int द्वारा घोषणा, और सबकुछ ठीक काम करना चाहिए। मैं क्या खो रहा हूँ?

संपादित करें: नीचे टिप्पणी ने बताया है कि दूसरा कोड स्निपेट विशेषज्ञता के बिना बजना और विजुअल C++ 2015

+5

बस FYI। यह बजना साथ में संकलित करने के लिए लगता है – Hayt

+1

यह भी विजुअल C++ 2015 के साथ संकलित रूप में आप यहाँ देख सकते हैं: http://webcompiler.cloudapp.net/ – Tunichtgut

+0

दोनों बजना 3.8 और जीसीसी 6.1.0 [डेमो] (http के लिए काम करता है: // coliru.stacked-crooked.com/a/14434a24d4688733) – Jarod42

उत्तर

3

एक B<int> की स्पष्ट इन्स्टेन्शियशन पहले यह A<int>::f() में प्रयोग किया जाता है इस समस्या को हल करता है। मैं जीसीसी A<int>::f() की परिभाषा में B<int> का एक अंतर्निहित इन्स्टेन्शियशन की कोशिश करता है मान लेते हैं। लेकिन A<int>::f() की परिभाषा समाप्त नहीं हुई है और जीसीसी ने मित्र घोषणा को खो दिया है। यह एक कंपाइलर समस्या की तरह दिखता है।

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 सदस्य समारोह के साथ सही ढंग से संकलित करने के लिए लगता है पूरे template class विशेष मामला है जब आप गैर विशेषज्ञ की अनुमति दी जाती है template सदस्य समारोह है, तो हो सकता है GCC उलझन में है, और मैं कारणों को पता नहीं है, लेकिन किसी भी तरह आप template class के गैर template सदस्य विशेष को दोस्ती की घोषणा नहीं कर सकते हैं। काम करने के लिए अस्थायी समाधान पूरे class template का विशेषज्ञ होगा।

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

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

फिर, A<int>::f को परिभाषित:

लिए class B:

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

template class B के लिए:

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

लेकिन मुझे लगता है Clang यहीं है, इस तरह के लिए कोई समस्या नहीं होनी चाहिए दोस्त declarati पर। यह शायद GCC में एक बग है।

संबंधित मुद्दे