2013-04-09 5 views
11

गैर प्रकार टेम्प्लेट पैरामीटर जाहिर है जो कि प्रकार नहीं हैं उदाहरण के लिए, कर रहे हैं:संरचना को टेम्पलेट गैर-प्रकार पैरामीटर के रूप में मान के रूप में क्यों नहीं पारित किया जा सकता है?

template<int x> 
void foo() { cout << x; } 

उस मामले में int के अलावा अन्य विकल्प होते हैं, और मैं this great answer का उल्लेख करना चाहते हैं।

अब, एक चीज है जो मुझे बग करता है: structs। पर विचार करें:

struct Triple { int x, y, z; }; 

Triple t { 1, 2, 3 }; 

template<Triple const& t> 
class Foo { }; 

अब, सामान्य nontype संदर्भ अर्थ विज्ञान का उपयोग कर, हम लिख सकते हैं:

Foo<t> f; 

क्या यहाँ ध्यान देने योग्य है कि tनहीं हो सकता है constexpr या यहाँ तक कि const, क्योंकि वह आंतरिक का तात्पर्य है लिंकेज, जिसका मूल रूप से मतलब है कि रेखा संकलित नहीं होगी। हम t को const extern के रूप में घोषित करके इसे बाईपास कर सकते हैं। अपने आप में एक सा अजीब हो सकता है यही कारण है, लेकिन एक है कि वास्तव में बनाया मुझे था क्यों यह संभव नहीं है:

Foo<Triple { 1, 2, 3 }> f; 

हम संकलक से एक बहुत सभ्य त्रुटि मिलती है:

error: Triple{1, 2, 3} is not a valid template argument for type const Triple& because it is not an lvalue.

हम कर सकते हैं ' मान द्वारा टेम्पलेट में Triple निर्दिष्ट करें, क्योंकि यह अस्वीकृत है। हालांकि, मैं कोड की उस छोटी सी रेखा के साथ वास्तविक समस्या को समझने में विफल रहा हूं। मूल्य पैरामीटर के रूप में structs का उपयोग करने की अनुमति न देने के पीछे तर्क क्या है। अगर मैं तीन int एस का उपयोग कर सकता हूं, तो तीन चींटियों की संरचना क्यों नहीं? यदि इसमें केवल छोटे विशेष सदस्य हैं, तो यह केवल तीन चरों की तुलना में संभालने में वास्तव में अलग नहीं होना चाहिए।

+2

मानक केवल int की अनुमति देता है, और सदस्य पॉइंटर्स मुझे लगता है। आप गैर-प्रकार के पैरामीटर के रूप में भी डबल या फ्लोट नहीं कर सकते हैं। या यहां तक ​​कि कॉन्स चार * जो सभी उपयोगी रहे हैं (और आश्चर्यजनक रूप से वीसी 6 पर काम किया)। निश्चित नहीं है कि सी ++ 11 के लिए कुछ भी बदले गए हैं, वास्तव में कुछ उत्तरों द्वारा निर्णय लेते हैं। – Pete

+1

@Pete 'const char * * में अलग-अलग स्थानों में लिखे गए समान अक्षरों के बीच असमानता की समस्या है, वही डबल/फ्लोट के लिए रहता है। इसके अलावा, आप संदर्भ छोड़ दिया। मेरा सवाल यह नहीं था कि यह संभव है (स्पष्ट रूप से नहीं), बल्कि यह * क्यों नहीं है *। –

+1

मुझे लगता है कि मानक के लिए कुछ भी कम करने के लिए संभावित रूप से कई संभावनाएं थीं। यह निर्दिष्ट करने के लिए एक बहुत ही आसान बात है कि यह केवल int के लिए सीमित है या नहीं। शायद यह 50 वर्षों के समय में अगले सी ++ मानक में उपलब्ध होगा। – Pete

उत्तर

12

मुझे लगता है कि "क्योंकि यह दोनों में ठीक से लागू करने और लागू करने के लिए मिक्टा में दर्द है" इसका मुख्य कारण यह नहीं है कि हमारे पास यह नहीं है। निश्चित रूप से, यह केवल थोड़ा सा काम करना आसान होगा, लेकिन फिर लोग शिकायत करेंगे कि संरचना टेम्पलेट पैरामीटर का उपयोग अन्य सभी टेम्पलेट पैरामीटर (आंशिक विशेषज्ञता पर विचार करें, या operator== के साथ क्या करना है) में समान परिस्थितियों में काम नहीं करता है।

मेरी राय में यह पूरे केक को पाने के लिए बहुत गन्दा है, और केवल एक छोटा टुकड़ा पर्याप्त संतुष्ट नहीं है, और संभवतः अधिक निराशाजनक है। इस छोटे से काम को बनाने से मुझे निम्नलिखित की तरह कुछ अधिक शक्ति नहीं मिलेगी, जिसमें बॉक्स के बाहर सभी प्रकार की चीजें (आंशिक विशेषज्ञता सहित) के साथ काम करने का अतिरिक्त लाभ है।

template <int X, int Y, int Z> 
struct meta_triple { 
    // static value getters 
    static constexpr auto x = X; 
    static constexpr auto y = Y; 
    static constexpr auto z = Z; 
    // implicit conversion to Triple 
    constexpr operator Triple() const { return { X, Y, Z }; } 
    // function call operator so one can force the conversion to Triple with 
    // meta_triple<1,2,3>()() 
    constexpr Triple operator()() const { return *this; } 
}; 
+3

'meta_triple' एक शानदार सृजन है। और यह उन समस्याओं को हल करता है जो मैंने वास्तव में अच्छी तरह से किया था। –

+0

+1: "मिक्टा" –

+0

के लिए क्या आप एक ऐसा कार्य कर सकते हैं जो दूसरी दिशा में जाता है जो 'ट्रिपल' को 'मेटा_ट्रिप्ल' में परिवर्तित करता है? – Eric

7

आप t को const extern के रूप में परिभाषित कर सकते हैं, जिससे यह बाहरी जुड़ाव हो। फिर निर्माण कार्य करता है:

struct Triple { int x, y, z; }; 

const extern Triple t { 1, 2, 3 }; 

template<Triple const& t> 
class Foo { }; 

Foo<t> f; 

Live example

कारण आप एक संदर्भ टेम्पलेट पैरामीटर के लिए अस्थायी नहीं पारित कर सकते हैं यह है कि पैरामीटर संदर्भ है। यदि आपको टेम्पलेट पैरामीटर const int& था और आपको 7 पास करने का प्रयास किया गया तो आपको वही त्रुटि मिल जाएगी। Example

संपादित

तीन int और तीन int रों युक्त एक struct के बीच अंतर यह है कि प्रकार int के सभी शाब्दिक वास्तव में एक ही मूल्य हैं (7 के सभी आवृत्तियां सिर्फ सात हैं) है, जबकि प्रत्येक निर्माता कॉल एक संरचना के लिए अवधारणात्मक रूप से एक नया उदाहरण बनाता है। इस काल्पनिक उदाहरण लें:

template <Triple t> 
struct Foo {}; 

Foo<Triple {1, 2, 3}> f1; 
Foo<Triple {1, 2, 3}> f2; 

मुझे लगता है कि यह एक ही टेम्पलेट इन्स्टेन्शियशन में "मैच" उन दो निर्माता आमंत्रण के लिए अतिरिक्त जटिलता को पेश करेंगे।

+3

एचएम, इसलिए यह इस तथ्य को उबालता है कि भाषा में पीओडी structs के लिए एक छोटा 'op ==' ​​नहीं है, और इस प्रकार दो अलग-अलग structs टेम्पलेट संदर्भ में अलग रहते हैं, भले ही उनके पास बिल्कुल वही डेटा हो। –

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

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