2010-10-21 26 views
8

मेरे कोड में क्या गलत है?सी ++ टेम्पलेट मित्र ऑपरेटर ओवरलोडिंग

template<int E, int F> 
class Float 
{ 
friend Float<E, F> operator+ (const Float<E, F> &lhs, const Float<E, F> &rhs); 
}; 

जी ++ बस रहता चेतावनी:

float.h:7: warning: friend declaration ‘Float<E, F> operator+(const Float<E, F>&, const Float<E, F>&)’ declares a non-template function

float.h:7: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning

मैं के रूप में चेतावनी नोट में बताया गया add <> after the function name here करने की कोशिश की है, लेकिन जी ++ मुझे एक त्रुटि देता है।

मैंने क्लैंग ++ के साथ कोड संकलित किया, यह ठीक था, बिल्कुल कोई चेतावनी नहीं थी।

+3

आप http://www.parashift.com/c++-faq-lite/templates.html#faq-35.16 पढ़ने के लिए – UncleBens

उत्तर

24

यह भाषा के एक मुश्किल पहलू के बारे में सिर्फ एक चेतावनी है। जब आप friend फ़ंक्शन घोषित करते हैं, तो यह घोषणा के वर्ग का सदस्य नहीं है। आप इसे सुविधा के लिए वहां परिभाषित कर सकते हैं, लेकिन यह वास्तव में नामस्थान से संबंधित है।

एक दोस्त समारोह जो एक टेम्पलेट नहीं है, एक वर्ग टेम्पलेट के अंदर की घोषणा, अभी भी नाम स्थान में एक गैर टेम्पलेट समारोह की घोषणा की। यह न तो वर्ग का सदस्य है, न ही स्वयं एक टेम्पलेट है। हालांकि, यह वर्ग टेम्पलेट द्वारा उत्पन्न है।

टेम्पलेट से गैर-टेम्पलेट फ़ंक्शंस उत्पन्न करना थोड़ा आलसी है। उदाहरण के लिए, आप class ब्लॉक के बाहर उस फ़ंक्शन के लिए घोषणा नहीं जोड़ सकते हैं। इसलिए आपको इसे class ब्लॉक के अंदर भी परिभाषित करना होगा, जो समझ में आता है क्योंकि क्लास टेम्पलेट इसे उत्पन्न करेगा।

दोस्तों के बारे में एक और मुश्किल बात यह है कि class Float {} के अंदर घोषणा नामस्थान में फ़ंक्शन घोषित नहीं करती है। आप इसे केवल तर्क-निर्भर अर्थ ओवरलोड रिज़ॉल्यूशन के माध्यम से ढूंढ सकते हैं, यानी यह निर्दिष्ट करते हुए कि एक तर्क में Float (या संदर्भ या सूचक) टाइप किया गया है। यह operator+ के लिए कोई मुद्दा नहीं है, क्योंकि इसे किसी भी तरह अधिभारित होने की संभावना है, और उपयोगकर्ता-परिभाषित प्रकारों को छोड़कर इसे कभी भी नहीं बुलाया जाएगा।

में कोई समस्या का एक उदाहरण के लिए, कल्पना आप एक रूपांतरण निर्माता Float::Float(Bignum const&) है। लेकिन Bignum में operator+ नहीं है। (क्षमा करें, प्रदूषित उदाहरण।) आप पर Bignum अतिरिक्त पर भरोसा करना चाहते हैं। अब my_bignum + 3 संकलित नहीं होगा क्योंकि न तो ऑपरेंड Float है इसलिए इसे friend फ़ंक्शन नहीं मिल रहा है।

शायद, आप, के बारे में चिंता करने के लिए जब तक प्रश्न में समारोह एक operator है के रूप में कुछ भी नहीं है।

या, आप friend बदल टेम्पलेट के रूप में अच्छी तरह से हो सकता है। उस मामले में, यह बजाय घोषित किया जा करने की जरूरत के बाहर परिभाषित किया जाना चाहिए class {} ब्लॉक, और यह पहले की घोषणा की, और अंदर परिभाषित किया।

template<int E, int F> // now this is a template! 
Float<E, F> operator+ (const Float<E, F> &lhs, const Float<E, F> &rhs); 

template<int E, int F> 
class Float 
{ 
    // deduce arguments E and F - this names operator+< E, F >. 
friend Float<E, F> operator+<> (const Float<E, F> &lhs, const Float<E, F> &rhs); 
}; 
+1

आपके तरह के उत्तर के लिए धन्यवाद। –

1

आप वास्तव में क्या करने के लिए के रूप में चेतावनी का कहना है की जरूरत है:

template<int E, int F> 
Float<E, F> operator+ (const Float<E, F> &lhs, const Float<E, F> &rhs); 

template<int E, int F> 
class Float 
{ 
friend Float<E, F> operator+<> (const Float<E, F> &lhs, const Float<E, F> &rhs); 
}; 

इस वर्ग टेम्पलेट का एक विशिष्ट उदाहरण के एक दोस्त ऑपरेटर टेम्पलेट की एक पूरी विशेषज्ञता की घोषणा की। प्रश्न के बारे में टिप्पणी में अंकलबेन्स ने कृपया a link to an explanation प्रदान किया है कि यह इतना जटिल क्यों है।

+0

@Potatoswatter चाहते हो सकता है: दोस्त घोषणा विशेष विशेषज्ञता वाणी वर्ग के एक दोस्त, नहीं? – sbi

+0

असल में, मैंने अभी @ एसबीआई कोड का परीक्षण किया है और यह मेरे जी ++ के साथ काम करता है। –

+0

@Zifei: यह स्निपेट काम करता है, लेकिन इसे फ़ंक्शन की परिभाषा को बदलने की आवश्यकता है। (क्षमा करें, मैंने फ़ंक्शन के रूप में परिवर्तन को नोटिस नहीं किया।) – Potatoswatter

3

यह काफी पुराना विषय है, लेकिन मुझे लगता है कि ऑपरेटर घोषित करने का सबसे आसान तरीका इसे फ्लोट क्लास के अंदर परिभाषित करना है।

template<int E, int F> 
class Float 
{ 
public: 
    friend Float operator+ (const Float &lhs, const Float &rhs) 
    { 
     // Whatever you need to do. 
    } 
}; 

वाक्य रचना लिखने और समझने के लिए आसान है और यह बिल्कुल वैसा ही काम करेंगे (सिवाय इसके कि यह inlined किया जाएगा), यह कोई एक सदस्य समारोह किया जाएगा।

एमएसडीएन: वर्ग घोषणाओं के भीतर परिभाषित मित्र कार्यों को संलग्न वर्ग के दायरे में नहीं माना जाता है; वे फ़ाइल के दायरे में हैं।

+0

नहीं, 'ऑपरेटर +' के मामले में, आम तौर पर 'ऑपरेटर + =' को सदस्य के रूप में लागू करने का सबसे आसान और सबसे अच्छा तरीका है, और उसके बाद 'ऑपरेटर +' को गैर-सदस्य गैर-मित्र के रूप में '+ = '। यह सुनिश्चित करता है कि आपके पास दोनों ऑपरेटर परिभाषित हैं और वे लगातार व्यवहार करते हैं। –

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