गैर-प्रकार टेम्पलेट पैरामीटर


93

मैं समझता हूं कि गैर-प्रकार का टेम्पलेट पैरामीटर एक निरंतर अभिन्न अभिव्यक्ति होना चाहिए। क्या कोई प्रकाश डाल सकता है ऐसा क्यों है?

template <std::string temp>
void foo()
{
     // ...
}
error C2993: 'std::string' : illegal type for non-type template parameter 'temp'.

मैं समझता हूं कि एक निरंतर अभिन्न अभिव्यक्ति क्या है। std::stringउपरोक्त स्निपेट की तरह गैर-स्थिर प्रकार की अनुमति नहीं देने के क्या कारण हैं ?


17
एक टेम्पलेट पैरामीटर को संकलन समय पर हल किया जाता है।
इटियेन डे मार्टेल

जवाबों:


121

आप ऐसा नहीं कर सकते इसका कारण यह है कि गैर-स्थिर अभिव्यक्तियों को संकलन-समय के दौरान पार्स और प्रतिस्थापित नहीं किया जा सकता है। वे रनटाइम के दौरान बदल सकते हैं, जिन्हें रनटाइम के दौरान एक नए टेम्पलेट की पीढ़ी की आवश्यकता होगी, जो संभव नहीं है क्योंकि टेम्पलेट एक संकलन-समय की अवधारणा है।

यहाँ मानक गैर-प्रकार के टेम्प्लेट मापदंडों की अनुमति देता है (14.1 [temp.param] p4))

एक गैर-टाइप टेम्पलेट-पैरामीटर में निम्न में से एक (वैकल्पिक रूप से cv- योग्य) प्रकार होंगे:

  • अभिन्न या गणना प्रकार,
  • सूचक वस्तु या सूचक कार्य करने के लिए,
  • ऑब्जेक्ट के लिए लैवल्यू संदर्भ या फ़ंक्शन के लिए लैवल्यू संदर्भ,
  • सदस्य को सूचक,
  • std::nullptr_t

6
@ALOToverflow: यह "पॉइंटर टू मेंबर" के अंतर्गत आता है। यह "पॉइंटर टू मेम्बर फंक्शन" या "पॉइंटर टू मेंबर डेटा" है।
Xio

4
यह ध्यान देने योग्य है कि ऑब्जेक्ट्स (या इंस्टेंस फील्ड्स) के लिए पॉइंटर्स के मामले में, ऑब्जेक्ट्स में स्टैटिक स्टोरेज की अवधि और लिंकेज (बाहरी पूर्व C ++ 11, C ++ 11 में आंतरिक या बाहरी) होना चाहिए, ताकि पॉइंटर्स उन्हें कर सकें संकलन समय पर बनाया जाए।
थियोडोर मर्डॉक

2
C ++ 20 में अब यह अनुमति दी गई है कि प्रकार में मजबूत संरचित समानता है, एक शाब्दिक है, कोई उत्परिवर्ती / अस्थिर सबोबेक्ट नहीं है और जहां स्पेसशिप ऑपरेटर सार्वजनिक है।
Rakete1111

73

यह अनुमति नहीं है।

हालाँकि, इसकी अनुमति है:

template <std::string * temp> //pointer to object
void f();

template <std::string & temp> //reference to object
void g();

C ++ स्टैंडर्ड (2003) में Standard14.1 / 6,7,8 देखें।


उदाहरण:

template <std::string * temp> //pointer to object
void f()
{
   cout << *temp << endl;
}

template <std::string & temp> //reference to object
void g()
{
     cout << temp << endl;
     temp += "...appended some string";
}

std::string s; //must not be local as it must have external linkage!

int main() {
        s = "can assign values locally";
        f<&s>();
        g<s>();
        cout << s << endl;
        return 0;
}

आउटपुट:

can assign values locally
can assign values locally
can assign values locally...appended some string

7
@ महेश: क्योंकि मूल रूप से जिस टेम्पलेट पर टेम्पलेट होता है, वह उस std::stringसूचक या संदर्भ वस्तु का पता होता है । यदि वह वैरिएबल स्थानीय था, तो संभवतः आपको हर बार फंक्शन के लिए अलग-अलग पते मिलेंगे।
Xio

11
@ महेश: आपको नहीं पता कि संकलन समय पर कॉल-स्टैक कैसा दिखता है। आपके कार्य से पहले, वहाँ 10 अन्य या 3 अन्य या फिर कई अन्य लोगों को बुलाया जा सकता था, इसलिए स्टैक पर पता, जिस पर स्ट्रिंग बनाई गई है कॉल से कॉल में बदल सकती है। जब आपके पास बाहरी लिंकेज वाली कोई वस्तु होती है, तो उसका पता संकलन / लिंकेज के दौरान तय किया जाता है।
Xio

2
@ Xeo " इसका पता संकलन / लिंकेज के दौरान तय किया गया है। " या नहीं, स्थानांतरित करने योग्य या स्थिति-स्वतंत्र कोड के लिए।
जिज्ञासु

1
यह उत्तर (वर्तमान में) ओपी के प्रश्न को संबोधित नहीं करता है, जो पूछ रहा था कि यह व्यवहार क्यों मौजूद है; यह उत्तर किसी भी स्पष्टीकरण की पेशकश के बिना केवल ओपी के उदाहरण को पुनर्स्थापित करता है।
क्क्सप्लसोन

1
मुझे पार्टी के लिए देर हो रही है, ऐसा लगता है कि स्मार्ट पॉइंटर्स भी काम नहीं करते हैं
निकोलस हम्फ्री

28

आपको टेम्प्लेट तर्कों को सक्षम करने की आवश्यकता है

template <std::string temp>
void f() {
 // ...
}

f<"foo">();
f<"bar">(); // different function!?

अब एक निहितार्थ के लिए वर्णों के एक अनूठे अनुक्रम के साथ आने की आवश्यकता होगी std::string, उस मामले के लिए, किसी अन्य मनमाने उपयोगकर्ता परिभाषित वर्ग, एक विशेष मूल्य को संग्रहीत करते हुए, जिसका अर्थ कार्यान्वयन के लिए ज्ञात नहीं है। और इसके अलावा, मनमाने ढंग से वर्ग की वस्तुओं के मूल्य की गणना संकलन समय पर नहीं की जा सकती है।

यह पोस्ट-सी ++ 0x के लिए टेम्पलेट पैरामीटर प्रकारों के रूप में शाब्दिक वर्ग प्रकारों की अनुमति देने पर विचार करने की योजना बनाई गई है, जो निरंतर अभिव्यक्तियों द्वारा प्रारंभ की जाती हैं। उन डेटा सदस्यों को उनके मूल्यों के अनुसार पुनरावर्ती रूप से मंगवाया जा सकता है (आधार कक्षाओं के लिए, उदाहरण के लिए हम गहराई-पहले, बाएं से दाएं ट्रैवर्सल लागू कर सकते हैं)। लेकिन यह निश्चित रूप से मनमाने वर्गों के लिए काम करने वाला नहीं है।


10

टेम्पलेट तर्क सूची के भीतर प्रदान किया गया एक गैर-प्रकार टेम्पलेट तर्क एक अभिव्यक्ति है जिसका मूल्य संकलन समय पर निर्धारित किया जा सकता है। इस तरह के तर्क होने चाहिए:

स्थिर अभिव्यक्ति, बाहरी लिंकेज के साथ कार्यों या वस्तुओं के पते, या स्थिर वर्ग के सदस्यों के पते।

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


आपने एक उद्धरण का उपयोग किया है, तो स्रोत क्या है? अगर यह उद्धरण के लिए एक स्रोत है तो मैं इसे अपवोट करना चाहूंगा।
गेब्रियल स्टेपल्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.