2009-03-16 12 views
28

मैं एक समारोह तो जैसे घोषणा की है:सी ++ टेम्पलेट्स, अपरिभाषित संदर्भ

template <typename T> 
T read(); 

और परिभाषित इसलिए की तरह:

template <typename T> 
T packetreader::read() { 
    offset += sizeof(T); 
    return *(T*)(buf+offset-sizeof(T)); 
} 

हालांकि, जब मैं अपने मुख्य() फ़ंक्शन में उपयोग करने का प्रयास करें:

packetreader reader; 
reader.read<int>(); 

मैं जी ++ से निम्न त्रुटि मिलती है:

g++ -o main main.o packet.o 
main.o: In function `main': 
main.cpp:(.text+0xcc): undefined reference to `int packetreader::read<int>()' 
collect2: ld returned 1 exit status 
make: *** [main] Error 1 

क्या कोई मुझे सही दिशा में इंगित कर सकता है?

+0

संभव डुप्लिकेट घोषित करने और टेम्पलेट कार्यों को लागू कर रहा है जानते हैं [अपरिभाषित संदर्भ जब स्ट्रिंग (जीसीसी) के साथ उपयोग किए गए खाके कार्य करने के लिए] (http: // stackoverflow।कॉम/प्रश्न/614233/अपरिभाषित-संदर्भ-टू-फ़ंक्शन-टेम्पलेट-जब-प्रयुक्त-स्ट्रिंग-जीसीसी) – outis

उत्तर

24

आपको export कीवर्ड का उपयोग करने की आवश्यकता है। हालांकि, मुझे नहीं लगता कि जी ++ का उचित समर्थन है, इसलिए आपको हेडर में टेम्पलेट फ़ंक्शन की परिभाषा को शामिल करने की आवश्यकता है ताकि अनुवाद इकाई इसका उपयोग कर सके। ऐसा इसलिए है क्योंकि टेम्पलेट का <int> 'संस्करण' नहीं बनाया गया है, केवल <typename T> 'संस्करण।'

#include .cpp फ़ाइल का एक आसान तरीका है। हालांकि, इससे समस्याएं पैदा हो सकती हैं, उदा। जब अन्य फ़ंक्शंस .cpp फ़ाइल में होते हैं। यह संकलन समय में भी वृद्धि होगी।

एक साफ रास्ता अपने आप ही .cpp फ़ाइल में अपने टेम्पलेट कार्यों ले जाते हैं, और शामिल है कि शीर्षक में याexport कीवर्ड का उपयोग करें और इसे अलग से संकलित करने के लिए है।

More information on why you should try and put template function definitions in its header file (and ignore export altogether).

+0

मेरे पैकेट.cpp कोड को packet.h में स्थानांतरित करने के लिए यह अच्छा विचार होगा और इसे पुनर्नामित करें कुछ "packet.hpp" जैसा कि मैंने अक्सर बढ़ावा में उपयोग किया है? –

+1

@ डैनियल, केवल तभी यदि आपके सभी फ़ंक्शन टेम्पलेट फ़ंक्शन हैं। अन्यथा, आप अपने कुछ कार्यों को आगे बढ़ने और .cpp फ़ाइल को रखने के साथ दूर हो सकते हैं। – strager

4

टेम्पलेट कार्यों के साथ सबसे अच्छा अभ्यास उन्हें हेडर फाइल में परिभाषित करने के लिए है। वे संकलन समय पर बनाए जाते हैं इसलिए कंपाइलर को ऐसा करने के लिए परिभाषा होती है।

जब टेम्पलेट्स के लिए export अधिक समर्थित होगा तो यह मामला नहीं होगा लेकिन अभी अभी भी इसका उपयोग शायद ही कभी किया जा सकता है।

+0

मैं 'निर्यात' का उपयोग करने की अनुशंसा नहीं करता हूं। Http://www.parashift.com/c++-faq-lite/templates.html#faq-35.14 के अनुसार, इसे C++ 0x मानक से बाहर कर दिया गया है। – uckelman

12

समस्या यह है कि फ़ंक्शन टेम्पलेट फ़ंक्शन नहीं है। यह आवश्यकतानुसार कार्यों को बनाने के लिए एक टेम्पलेट है।

तो काम करने के लिए एक टेम्पलेट के लिए, कंपाइलर को जानबूझकर जानकारी के दो टुकड़ों की आवश्यकता होती है: टेम्पलेट स्वयं, और उस प्रकार को प्रतिस्थापित किया जाना चाहिए। यह फ़ंक्शन कॉल के विपरीत है, जो संकलक उत्पन्न हो सकता है जैसे ही यह जानता है कि फ़ंक्शन मौजूद है। यह जानने की आवश्यकता नहीं है कि फ़ंक्शन क्या करता है, बस यह void Frobnicate(int, float) जैसा दिखता है, या जो भी उसका हस्ताक्षर है।

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

0

क्या उनके कोई संकलक समर्थन टेम्पलेट अलग संकलन है?

मैं आम बात हेडर फाइल में की

+0

Comau मुझे विश्वास है। और एमएसवीसी का आधुनिक संस्करण * हो सकता है * लेकिन मैंने खुद को चेक नहीं किया है। – vava

+0

नवीनतम वीएस -2008 अभी तक निर्यात कीवर्ड का समर्थन नहीं करता है। ऐसा लगता है कि एमएस लोगों ने भविष्य में समर्थन के लिए इस कीवर्ड को आरक्षित किया है: चेतावनी C4237: 'export' कीवर्ड अभी तक समर्थित नहीं है, लेकिन भविष्य के उपयोग के लिए आरक्षित है –

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

  • कोई संबंधित समस्या नहीं^_^