2015-03-02 10 views
13

मान लें हम इस तरह const char * के गैर प्रकार पैरामीटर के साथ एक टेम्पलेट समारोह करते हैं:कुछ कॉन्स char * संकलन समय पर अनुपलब्ध हैं?

template <const char * MESSAGE> void print() { 
    std::cout << MESSAGE << '\n'; 
} 

इस टेम्पलेट का उपयोग कर लॉग के रूप में एक समस्या नहीं होगा के रूप में MESSAGE संकलन समय पर निष्कर्ष निकाला जा सकता है, तो निम्नलिखित का उपयोग करता है कानूनी हैं:

namespace { 
    char namespace_message[] = "Anonymous Namespace Message"; 
    constexpr char namespace_constexpr_message[] = "Anonymous Namespace Constexpr Message"; 
} 

char message[] = "Message"; 
constexpr char constexpr_message[] = "Constexpr Message"; 

int main() 
{ 
    print<namespace_message>(); 
    print<namespace_constexpr_message>(); 

    print<message>(); 
    print<constexpr_message>(); 

    return 0; 
} 

लेकिन नीचे वाले (see here) नहीं हैं:

namespace { 
const char namespace_const_message[] = "Anonymous Namespace Const Message"; 
} 

const char const_message[] = "Const Message"; 

int main() 
{ 
    print<namespace_const_message>(); 
    print<const_message>(); 
    print<"Literal">(); 

    return 0; 
} 

कोड द्वारा उत्पन्न त्रुटियों ऊपर निम्नलिखित हैं:

the value of '{anonymous}::namespace_const_message' is not usable in a constant expression

मैं क्यों namespace_const_message एक निरंतर अभिव्यक्ति में namespace_message है, जबकि प्रयोग करने योग्य नहीं है नहीं मिलता है; अगर मुझे निरंतर अभिव्यक्ति में उपयोग करने में असमर्थ होने के लिए शर्त लगानी पड़े तो मैं निरंतर अभिव्यक्ति के लिए शर्त लगाऊंगा, लेकिन वह वह है जो पहले से ही निरंतर अभिव्यक्ति के रूप में काम करता है!

note: '{anonymous}::namespace_const_message' was not declared 'constexpr'

namespace_messageconstexpr के रूप में घोषित किया गया था और एक निरंतर अभिव्यक्ति में प्रयोग किया जाता है और इसके मूल्य संकलन समय पर निष्कर्ष निकाला गया है। constexpr की आवश्यकता क्यों है यदि अभिव्यक्ति const है और यदि आवश्यक नहीं है तो आवश्यकता नहीं है?

अनाम नामस्थान के बाहर के मूल्यों के लिए भी जाता है, मैं मूल्यों को एक आंतरिक संबंध स्थान में रखकर संकलन-समय-स्थिरता को मजबूर करने की कोशिश कर रहा था लेकिन यह स्पष्ट है कि मैं असफल रहा हूं।

अंत में, पिछले त्रुटि:

'"Literal"' is not a valid template argument for type 'const char*' because string literals can never be used in this context

तो, आश्चर्यजनक रूप से एक स्ट्रिंग शाब्दिक टेम्पलेट तर्क के रूप में नहीं किया जा सकता (कम से कम यह एक आश्चर्य मेरे लिए था), लेकिन जब तक स्ट्रिंग के रूप में (अच्छी तरह से, एक अक्षरों की एक नल-टर्मिनेटेड सरणी के लिए सूचक) एक संकलन-समय मान है जिसे इसे गैर-प्रकार के टेम्पलेट पैरामीटर के रूप में उपयोग किया जा सकता है: वे संकलित समय पर उपलब्ध हैं जब तक कि वे "एक लालसा हैं" (लेकिन वे हैं already lvalues!)।

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

तो, यहां सवाल क्या है?

  • क्यों namespace_const_message और const_message संकलन समय पर उपलब्ध नहीं हैं और इस तरह print टेम्पलेट समारोह में मना?
  • क्या स्ट्रिंग अक्षर के बारे में मेरा अनुमान सही है?

धन्यवाद।

उत्तर

9

बाहरी लिंकेज के लिए आवश्यक टेम्पलेट का तत्काल चर, और const अंतर्निहित आंतरिक संबंध था।तो तुम लिखने के लिए है:

extern char const constMessage[] = "Const message"; 

(एक अन्य विकल्प होगा तो वह एक स्थिर वर्ग के सदस्य होने के लिए स्टेटिक वर्ग के सदस्यों हमेशा बाह्य संबंध है।।)

स्ट्रिंग शाब्दिक के मामले कुछ में है इसी तरह के तरीके: उनके प्रकार char const[] है। लेकिन यह भी बदतर है: टेम्पलेट इंस्टॉलेशन (कम से कम शुरुआती वाले) को एक नाम की आवश्यकता है, और एक स्ट्रिंग शाब्दिक में कोई नहीं है। बात करने के लिए इससे भी अधिक, यह अनिर्दिष्ट है समान स्ट्रिंग शाब्दिक एक ही वस्तु हैं या नहीं, इसलिए में निम्नलिखित:

template <char const* m> 
struct Toto { char const* f() const; }; 

Toto <"titi"> t1; 
Toto <"titi"> t2; 

यह अनिर्दिष्ट होगा कि क्या t1 और t2 एक ही प्रकार की थी या नहीं।

+1

संबंध के बारे में महान जवाब! अच्छा है। मैं आपको लिंक मुद्दे के बारे में अधिक जानकारी के लिए पूछना चाहता हूं; AFAIK एक अज्ञात नेमस्पेस आंतरिक लिंकेज को मजबूर करता है और आप कहते हैं कि * बाहरी लिंकेज के लिए आवश्यक टेम्पलेट का तत्काल चर * *, टेम्पलेट में 'नेमस्पेस_मेसेज' और 'नेमस्पेस_कॉनएक्सएक्स_मेसेज' क्यों स्वीकार किए जाते हैं? क्या आप (कृपया) अपना उत्तर बढ़ा सकते हैं? –

+1

@PaperBirdMaster: यह अनाम नामों के बारे में सच नहीं है। यह सी ++ 11 के फुटनोट 94: _ में स्पष्ट है: "हालांकि एक अनाम नामस्थान में इकाइयों के पास बाहरी संबंध हो सकता है, लेकिन वे प्रभावी रूप से उनके अनुवाद इकाई के नाम से योग्यता प्राप्त कर सकते हैं और इसलिए किसी भी अन्य अनुवाद इकाई से कभी नहीं देखा जा सकता है।" _ नियम 3.5/3 और 3.5/4 में दिए जाते हैं। –

+0

@LightnessRacesinOrbit ठीक है, इसलिए मैं नामित नामस्थानों के बारे में गलत था: वे आंतरिक संबंध को मजबूर नहीं करते हैं, उनके पास आंतरिक संबंध हो सकता है। स्पष्टीकरण के लिए धन्यवाद। –

3
ग से

++ 11 मानक §14.3.2.1

Template non-type arguments

A template-argument for a non-type, non-template template-parameter shall be one of:

  1. for a non-type template-parameter of integral or enumeration type, a converted constant expression (5.19) of the type of the template-parameter; or
  2. the name of a non-type template-parameter; or
  3. a constant expression (5.19) that designates the address of an object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or
  4. a constant expression that evaluates to a null pointer value (4.10); or
  5. a constant expression that evaluates to a null member pointer value (4.11); or
  6. a pointer to member expressed as described in 5.3.1; or
  7. an address constant expression of type std::nullptr_t.

आपके प्रश्नों के लिए:

क्यों namespace_const_message और const_message संकलन समय पर उपलब्ध है और इस तरह प्रिंट में मना नहीं कर रहे हैं टेम्पलेट समारोह?

यही कारण है कि constexpr मौजूद है। उनका उपयोग किया जा सकता है जहां इसकी आवश्यकता है संकलन-समय मूल्यांकन, इस प्रकार टेम्पलेट-तर्क होने के लिए उपलब्ध है।

क्या स्ट्रिंग अक्षर के बारे में मेरा अनुमान सही है?

वहाँ बहस के बाद इस अधिकार के बारे में एक नोट है:

Note: A string literal (2.14.5) does not satisfy the requirements of any of these categories and thus is not an acceptable template-argument.

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