2017-03-09 6 views
9

मैं इस कोड है:मुझे इस विशेष मामले में टेम्पलेट पैरामीटर की आवश्यकता क्यों नहीं है?

struct Base {}; 

template<typename T> 
struct Foo : Base {}; 

struct Bar { 
    template<typename T> //   v--- What's happening here? 
    Bar(T foo) : baz{std::make_unique<Foo>(foo)} {} 

    std::unique_ptr<Base> baz; 
}; 

एक आश्चर्य, जीसीसी के रूप में और बजना स्वीकार करते हैं और यह संकलित करता है। ऐसा लगता है कि Foo के टेम्पलेट पैरामीटर को कम करना प्रतीत होता है, लेकिन यह समझ में नहीं आता है। कंपेलर कैसे स्वीकार करते हैं कि भले ही std::make_unique का कोई ओवरलोड न हो, जो टेम्पलेट टेम्पलेट पैरामीटर लेता है? Live example

+3

एर ... उस कन्स्ट्रक्टर के साथ 'बार' ऑब्जेक्ट बनाने का प्रयास करें, यदि आप कर सकते हैं। फिर हमें बताएं कि संकलक कोड स्वीकार करता है या नहीं। – WhiZTiM

+0

@WhiZTiM यह कोड को अस्वीकार करता है।मुझे अभी भी यह वास्तव में अजीब लगता है कि दोनों कंपाइलर मेल नहीं खाते टेम्पलेट पैरामीटर प्रकार के बारे में शिकायत नहीं करते हैं। –

उत्तर

8

वहाँ जहां एक टेम्पलेट हमेशा अमान्य है, कोई बात नहीं क्या टेम्पलेट तर्क आपूर्ति की जाती है कुछ स्थितियों, लेकिन कर रहे हैं संकलक, कि यह पता लगाने के लिए सक्षम नहीं है, क्योंकि यह हर प्रतिस्थापन की कोशिश करने की क्षमता नहीं है टेम्पलेट तर्कों का संभावित सेट। मानक के अनुसार ([temp.res]/8):

कोई वैध विशेषज्ञता एक टेम्पलेट के लिए उत्पन्न किया जा सकता है, और उस टेम्पलेट instantiated नहीं है, टेम्पलेट बीमार का गठन है, कोई निदान आवश्यक ।

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

टेम्पलेट तर्कों के बिना टेम्पलेट के नाम का उपयोग करना अवैध नहीं है। कुछ परिस्थितियां हैं जहां संकलक तर्क को कम कर सकता है। उदाहरण के लिए:

template <class T> 
void foo(T x); 

int main() { 
    void (*p)(int) = foo; // p points to foo<int> 
} 

अपने कोड में, यह पता चला है कि आप एक संदर्भ में, जहां टेम्पलेट तर्क निष्कर्ष निकाला नहीं जा सकता है में Foo का उपयोग किया है कि। अगर कंपाइलर्स चालाक थे, तो वे इसे समझ लेंगे। लेकिन तथ्य यह है कि उन्होंने इसे समझने के लिए प्रबंधन नहीं किया है इसका मतलब यह नहीं है कि आपका कोड सही है।

+1

अच्छा कोड स्निपेट, यह नहीं पता था कि ऐसा कोड मान्य है और इस तरह के संदर्भ में टेम्पलेट पैरामीटर को घटाया जा सकता है। – vsoftco

4

कारण यह काम है क्योंकि सी ++ वास्तव में टेम्पलेट फ़ंक्शंस नहीं बनाते हैं जब तक उन्हें कोड में कहीं से भी नहीं कहा जाता है। इस उदाहरण में, चूंकि आपका कोड कभी भी Bar बनाने का प्रयास नहीं करता है, इसलिए आपका टेम्पलेट एक-arg Bar कन्स्ट्रक्टर कभी उत्पन्न नहीं होता है, इसलिए संकलक को यह जांचने की आवश्यकता नहीं होती है कि कोड सही है या नहीं।

टेम्पलेट फ़ंक्शंस जितनी जल्दी हो सके संकलक द्वारा उत्पन्न होते हैं, और वे केवल इन प्रकारों के आधार पर उत्पन्न होते हैं। तो, आप एक Bar इसलिए की तरह बनाने की कोशिश करता है, तो: क्योंकि यह अब जानता कोड गलत है

error C2955: 'Foo' : use of class template requires template argument list 

:

Foo<int> f; 
Bar b = Bar(f); 

संकलक निर्माता उत्पन्न करने के लिए कोशिश करते हैं और तरह एक त्रुटि के साथ विफल हो जाएगा।

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

+0

कंपाइलर कुछ टेम्पलेट चेक भी करता है, लेकिन इस मामले में वास्तव में कोई चेक नहीं किया जाता है। नियम वास्तव में बहुत जटिल हैं, विस्तृत विवरण के लिए [सी ++ टेम्पलेट्स: एक पूर्ण मार्गदर्शिका] देखें (https://www.amazon.com/ टेम्पलेट्स- पूर्ण- गाइड- डेविड- वेंडेवोर्डे/डीपी/0201734842)। – vsoftco

+0

हां आप sfinae के माध्यम से अवधारणा को अनुकरण करके किसी भी टेम्पलेट पैरामीटर को बाधित कर सकते हैं। –

+1

@GuillaumeRacicot यह आपको उन प्रकारों को बाधित करने की अनुमति नहीं देता है जिनका उपयोग टेम्पलेट फ़ंक्शन को तुरंत चालू करने के लिए किया जा सकता है। यह आपको केवल कुछ अधिभारों में सिंटैक्स त्रुटियों को बनाने की अनुमति देता है, ताकि ओवरलैल रिज़ॉल्यूशन में उस त्वरण को कम प्राथमिकता दी जाएगी। किसी भी प्रकार का अभी भी किसी भी टेम्पलेट प्रकार के लिए उपयोग किया जा सकता है, इसलिए संकलक को अभी भी संभावित उम्मीदवार के रूप में किसी भी प्रकार पर विचार करने की आवश्यकता है। जैसा कि मैंने कहा, एक विशिष्ट तत्कालता का चयन करने से पहले सिंटैक्स त्रुटियों की जांच करना असंभव हो जाता है। –

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