2008-09-12 11 views
25

मान लीजिए कि मेरे पास fileA.h है जो टेम्पलेट फ़ंक्शन SomeFunc<T>() के साथ classA श्रेणी घोषित करता है। यह फ़ंक्शन सीधे हेडर फ़ाइल में लागू किया गया है (जैसा कि टेम्पलेट फ़ंक्शंस के लिए सामान्य है)। अब मैं (SomeFunc<int>() के लिए) fileA.C (यानी हेडर फ़ाइल में नहीं) में एक विशेष कार्यान्वयन जोड़ता हूं।सी ++ फ़ंक्शन के टेम्पलेट विशेषज्ञता की दृश्यता

यदि अब मैं किसी अन्य कोड (शायद किसी अन्य लाइब्रेरी से) SomeFunc<int>() पर कॉल करता हूं, तो क्या यह सामान्य संस्करण या विशेषज्ञता कहलाता है?

मुझे अभी यह समस्या है, जहां कक्षा और फ़ंक्शन एक लाइब्रेरी में रहते हैं जिसका उपयोग दो अनुप्रयोगों द्वारा किया जाता है। और एक एप्लिकेशन सही ढंग से विशेषज्ञता का उपयोग करता है, जबकि एक और ऐप जेनेरिक फॉर्म का उपयोग करता है (जो बाद में रनटाइम समस्याओं का कारण बनता है)। अंतर क्यों? क्या यह लिंकर विकल्प आदि से संबंधित हो सकता है? यह जी ++ 4.1.2 के साथ लिनक्स पर है।

उत्तर

0

जब तक विशेष टेम्पलेट फ़ंक्शन हेडर फ़ाइल में सूचीबद्ध नहीं होता है, तो अन्य एप्लिकेशन को विशेष संस्करण का कोई ज्ञान नहीं होगा। समाधान हेडर में SomeFunc<int>() जोड़ें।

9

क्या आपने अपनी हेडर फ़ाइल में पैरामीटर के साथ प्रोटोटाइप जोड़ा है?

मेरा मतलब है अगर नहीं है कि शायद यही कारण है fileA.h

template<> SomeFunc<int>(); 

में कहीं नहीं है।

0

ब्रैंडन: यही मैंने सोचा - विशेष कार्य कभी नहीं कहा जाना चाहिए। मैंने जो दूसरे आवेदन का उल्लेख किया है, उसके लिए कौन सा सच है। हालांकि, पहला ऐप स्पष्ट रूप से विशेष रूप से कॉल करता है भले ही हेडर फ़ाइल में विशेषज्ञता घोषित न हो!

मैं मुख्य रूप से, क्योंकि पहली बार एप्लिकेशन एक इकाई परीक्षण है ज्ञान की खोज यहाँ :-), और यह एक बग है कि परीक्षण में लेकिन असली अनुप्रयोग में प्रकट नहीं होता है करने के लिए दुर्भाग्यपूर्ण है ...

(पी एस : मैं वास्तव में शीर्षक में विशेषज्ञता की घोषणा के द्वारा इस विशिष्ट बग तय कर दी है, लेकिन क्या अन्य इसी तरह के कीड़े अभी भी छिपी हो सकती)

2
चश्मा प्रति

, अपने विशेष समारोह टेम्पलेट कभी नहीं fileA.C बाहर बुलाया जाना चाहिए, जब तक आप export? टेम्पलेट परिभाषा, जो कोई कंपाइलर (Comau को छोड़कर) वर्तमान में समर्थन करता है (या यह भविष्य के लिए योजना बनाई है)।

दूसरी ओर, एक बार समारोह टेम्पलेट instantiated है, वहाँ एक समारोह संकलक एक टेम्पलेट है कि अब और नहीं करने के लिए दिख रहा है। जीसीसी विभिन्न संकलक इकाइयों में इस परिभाषा का दोबारा उपयोग कर सकता है क्योंकि मानक कहता है कि प्रत्येक टेम्पलेट को केवल दिए गए तर्कों के एक सेट के लिए तत्काल तत्काल किया जाएगा [temp.spec]। फिर भी, चूंकि टेम्पलेट निर्यात नहीं किया जाता है, इसलिए यह संकलन इकाई तक ही सीमित होना चाहिए।

मेरा मानना ​​है कि जीसीसी संकलन इकाइयों में तत्काल टेम्पलेट्स की अपनी सूची साझा करने में यहां एक बग का पर्दाफाश कर सकता है। आम तौर पर, यह एक उचित अनुकूलन है, लेकिन यह खाता है जो इसे सही ढंग से करने के लिए प्रतीत नहीं होता है में समारोह विशेषज्ञताओं लेना चाहिए।

0

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

किसी भी मामले में कोई चेतावनी नहीं थी। मुझे इस तरह का संदेह है, यही कारण है कि मैंने प्रयोग किया था।

मुझे लगता है कि टेम्पलेट फ़ंक्शन वही व्यवहार करेंगे, जैसा कि अन्य कंपाइलर्स होगा।

22

यह एक त्रुटि है जो एक टेम्पलेट के लिए विशेषज्ञता है जो कॉल के बिंदु पर दिखाई नहीं दे रहा है। दुर्भाग्यवश, इस त्रुटि का निदान करने के लिए कंपाइलरों की आवश्यकता नहीं है, और फिर वे आपके कोड के साथ जो कुछ भी पसंद करते हैं, कर सकते हैं (मानक में यह "बीमार गठित, कोई निदान आवश्यक नहीं है")।

तकनीकी तौर पर, आप हेडर फाइल में विशेषज्ञता परिभाषित करने की जरूरत है, लेकिन लगभग हर संकलक इस संभाल लेंगे जैसा कि आप उम्मीद कर सकते हैं:

: इस नए "extern टेम्पलेट" सुविधा के साथ सी ++ 11 में तय हो गई है
extern template<> SomeFunc<int>(); 

यह स्पष्ट रूप से घोषित करता है कि विशेष विशेषज्ञता को कहीं और परिभाषित किया गया है। कई कंपाइलर्स पहले से ही इसका समर्थन करते हैं, कुछ extern के बिना कुछ और कुछ।

0

@ [एंथनी विलियम्स],

क्या आप वाकई extern template instantiations साथ extern टेम्पलेट घोषणाओं भ्रमित नहीं कर रहे हैं कर रहे हैं? जो मैं देखता हूं, extern templateकेवल स्पष्ट तत्कालता के लिए उपयोग किया जाना चाहिए, विशेषज्ञता के लिए नहीं (जो अंतर्निहित तत्कालता का तात्पर्य है)।

स्पष्ट-विशेषज्ञता: [temp.expl.spec] extern कीवर्ड का उल्लेख नहीं करता
        template <>घोषणा

+0

Damnit, उपयोगकर्ता नाम के स्वत: जोड़ने काम नहीं करता। –

3

मैं एक ही समस्या थी जीसीसी 4 के साथ, यहां मैंने इसे हल किया है। पिछली टिप्पणियों से विश्वास करने के लिए मुझे नेतृत्व करने के लिए यह एक आसान समाधान था। पिछले पोस्ट विचार सही थे लेकिन उनके वाक्यविन्यास मेरे लिए काम नहीं करते थे।


    ----------header----------------- 
    template < class A > 
    void foobar(A& object) 
    { 
     std::cout << object; 
    } 

    template <> 
    void foobar(int); 

    ---------source------------------ 
    #include "header.hpp" 

    template <> 
    void foobar(int x) 
    { 
     std::cout << "an int"; 
    } 

+0

एसओबी जो पूर्वावलोकन में स्वरूपित था! माफ़ कीजिये –

1

एंथनी विलियम्स कहते हैं, extern template निर्माण ऐसा करने का सही तरीका है, लेकिन उसके बाद से नमूना कोड अधूरा है और कई वाक्य रचना त्रुटियाँ हैं, यहाँ एक पूर्ण समाधान है।

fileA.h:

namespace myNamespace { 
    class classA { 
    public: 
     template <class T> void SomeFunc() { ... } 
    }; 

    // The following line declares the specialization SomeFunc<int>(). 
    template <> void classA::SomeFunc<int>(); 

    // The following line externalizes the instantiation of the previously 
    // declared specialization SomeFunc<int>(). If the preceding line is omitted, 
    // the following line PREVENTS the specialization of SomeFunc<int>(); 
    // SomeFunc<int>() will not be usable unless it is manually instantiated 
    // separately). When the preceding line is included, all the compilers I 
    // tested this on, including gcc, behave exactly the same (throwing a link 
    // error if the specialization of SomeFunc<int>() is not instantiated 
    // separately), regardless of whether or not the following line is included; 
    // however, my understanding is that nothing in the standard requires that 
    // behavior if the following line is NOT included. 
    extern template void classA::SomeFunc<int>(); 
} 

fileA.C:

#include "fileA.h" 

template <> void myNamespace::classA::SomeFunc<int>() { ... }