2013-02-25 19 views
11

मेरे पास एक टेम्पलेट क्लास है जिसे मैं एक विधि के साथ शीर्षलेख में घोषित करता हूं और शीर्षलेख में उस विधि की कोई परिभाषा नहीं देता हूं। एक .cc फ़ाइल में, मैं उस विधि के विशेषज्ञों को कभी भी शीर्षलेख में घोषित किए बिना परिभाषित करता हूं। एक अलग .cc फ़ाइल में, मैं विभिन्न टेम्पलेट पैरामीटर के लिए विधि को कॉल करता हूं जिसके लिए विशेषज्ञता मौजूद है। यह इस तरह दिखता है:हेडर में घोषणा के बिना टेम्पलेट क्लास सदस्य विशेषज्ञता

foo.h:

template<typename T> 
class Foo { 
public: 
    static int bar(); 
}; 

foo.cc:

#include "foo.h" 

template<> 
int Foo<int>::bar() { 
    return 1; 
} 

template<> 
int Foo<double>::bar() { 
    return 2; 
} 

main.cc:

#include <iostream> 
#include "foo.h" 

int main(int argc, char **argv) { 
    std::cout << Foo<int>::bar() << std::endl; 
    std::cout << Foo<double>::bar() << std::endl; 
    return 0; 
} 

इस कार्यक्रम जीसीसी के साथ संकलित करता है तथा लिंक सफलतापूर्वक सभी सी ++ मानकों के लिए 4.7.2 (सी ++ 98, gnu ++ 98, सी ++ 11, और gnu ++ 11)। आउटपुट है:

1 
2 

यह मुझे समझ में आता है। चूंकि main.cc अनुवाद इकाई को bar() या किसी भी विशेषज्ञता की परिभाषा नहीं दिखाई देती है, इसलिए यह bar() पर किसी अन्य अनुवाद इकाई में bar() की एक विशेषीकृत परिभाषा के स्पष्ट तत्काल उपयोगों की अपेक्षा करने के लिए कॉल की अपेक्षा करता है। लेकिन चूंकि नाम उलझन में अनुमान लगाया जा सकता है, foo.cc में विशेषज्ञताएं समान प्रतीक नामों के समान तत्काल परिभाषा के समान प्रतीक नाम हैं, इसलिए main.cc उन विशेषज्ञताओं का उपयोग करने में सक्षम है, जिन्हें कभी भी उस अनुवाद इकाई में घोषित नहीं किया जाता है।

मेरा प्रश्न यह है: क्या यह एक दुर्घटना है, या यह व्यवहार सी ++ मानक द्वारा अनिवार्य है? दूसरे शब्दों में, क्या यह कोड पोर्टेबल है?

सबसे प्रासंगिक पूर्व प्रश्न जो मुझे मिल सकता है Declaration of template class member specialization है, लेकिन इसमें इस विशेष मामले को शामिल नहीं किया गया है।

(यदि आप सोच रहे हैं कि यह मेरे लिए क्यों मायने रखता है, तो ऐसा इसलिए है क्योंकि मैं इस तरह के कोड का उपयोग संकलन-समय लुक-अप तालिका के रूप में कर रहा हूं और यदि मैं विशेषज्ञता घोषित नहीं करता तो यह बहुत छोटा है ।)

+2

यह एक अच्छा पहला सवाल है! मुझे लगता है कि आईबीएम का कंपाइलर आपको बाहरी कीवर्ड का उपयोग करके अपनी विशेषज्ञता घोषित करने की अनुमति देता है, लेकिन इसे कभी नहीं किया। –

उत्तर

8

The Standard (सी ++ 11) की आवश्यकता है कि स्पष्ट विशेषज्ञताओं घोषित किया (लेकिन जरूरी परिभाषित नहीं) इससे पहले कि वे पहले उपयोग किया जाता है:

(14.7.3/6) तो एक टेम्पलेट, एक सदस्य टेम्पलेट या क्लास टेम्पलेट का सदस्य स्पष्ट रूप से विशिष्ट है, तो उस विशेषज्ञता के पहले उपयोग से पहले विशेषज्ञता घोषित की जाएगी जो प्रत्येक निशान में एक अंतर्निहित तत्कालता का कारण बन जाएगी एनएसलेशन यूनिट जिसमें ऐसा उपयोग होता है; कोई निदान की आवश्यकता नहीं है। यदि कार्यक्रम एक स्पष्ट विशेषज्ञता के लिए परिभाषा प्रदान नहीं करता है और या तो विशेषज्ञता का उपयोग ऐसे तरीके से किया जाता है जो एक निहित तत्कालता का कारण बनता है या सदस्य वर्चुअल सदस्य फ़ंक्शन होता है, तो प्रोग्राम खराब बना हुआ है, कोई निदान आवश्यक नहीं है । एक स्पष्ट तत्कालता कभी स्पष्ट स्पष्टीकरण के लिए उत्पन्न नहीं होती है जिसे घोषित किया जाता है लेकिन परिभाषित नहीं किया जाता है। [...]

मेरा मानना ​​है कि यह व्यवहार में केवल तभी प्रभाव डालता है जब आपकी प्राथमिक टेम्पलेट परिभाषा में सदस्य कार्यों में से किसी एक के गैर-विशिष्ट संस्करण की परिभाषा शामिल होती है। क्योंकि उस स्थिति में, जब स्पष्ट विशेषज्ञता घोषित नहीं की जाती है, तो मौजूदा प्राथमिक परिभाषा का उपयोग कोड में फ़ंक्शन इनलाइन को संकलित करने के लिए किया जा सकता है, और विशेषज्ञता का समय लिंक-टाइम पर उपयोग नहीं किया जाएगा।

दूसरे शब्दों में, यदि प्राथमिक टेम्पलेट परिभाषा में सदस्य फ़ंक्शन की कोई परिभाषा नहीं है, तो आपके लिंकर चाल को शायद अभ्यास में काम करने की उम्मीद की जा सकती है, लेकिन यह मानक कहता है, और यह इसके अनुरूप नहीं होगा जैसे ही आप प्राथमिक टेम्पलेट में इनलाइन फ़ंक्शन परिभाषा जोड़ते हैं, आपको वास्तविक परेशानी में डाल सकते हैं।

+0

धन्यवाद। निश्चित रूप से सहमत हैं कि प्राथमिक टेम्पलेट में इनलाइन परिभाषा होने पर यह कोड टूटा हुआ है। लेकिन यह देखते हुए कि मानक नहीं है, मानक इस मामले में क्या होता है इसके बारे में कुछ भी कहता है? यह अनुच्छेद इसे कवर करने के लिए प्रतीत नहीं होता है। –

+0

@ ट्रिस्टनस्चमेल्चर मेरा मानना ​​है कि ऊपर दिए गए अनुभाग में सभी मामलों को शामिल किया गया है (जब तक कोई अपवाद नहीं है जहां मैंने देखा नहीं था)। यह स्पष्ट रूप से कहता है कि उपयोग से पहले स्पष्ट विशेषज्ञता घोषित की जानी चाहिए। तो यदि हेडर फ़ाइल इसे घोषित नहीं करती है, लेकिन main.cpp (जिसमें हेडर शामिल है, लेकिन .cc नहीं) इसका उपयोग करता है, यह मानक का उल्लंघन करता है। – jogojapan

+1

मैं देखता हूं। मैंने सोचा था कि "निहित तत्काल" शब्द मुख्य.सीसी में उपयोग को कवर नहीं करेगा क्योंकि अनिवार्य 'बार()' की कोई परिभाषा गुंजाइश में नहीं है, लेकिन 14.7.1 ऐसा लगता है कि यह किसी भी तत्काल तत्काल के रूप में गिना जाता है। –

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