2014-08-31 12 views
8

मैंने एक कॉन्स्टेक्स फ़ंक्शन लिखा जो एक सरणी देता है।constexpr रिटर्निंग सरणी, जीसीसी चेतावनी

#include <iostream> 

constexpr auto get_str(void) 
-> const char(&)[4] { 
    return { 'T', 'E', 'S', 'T' }; 
} 

constexpr int sum(const char(&str)[4]){ 
    return str[0] + str[1] + str[2] + str[3]; 
} 

int main(void){ 

    constexpr int s = sum(get_str()); 

    std::cout << s << std::endl; 

    return 0; 
} 

जी ++ 4.8 सही ढंग से कोड को संकलित करता है, लेकिन निम्न चेतावनी जारी करता है:

test.cpp: In function ‘constexpr const char (& get_str())[4]’: 
test.cpp:5:30: warning: returning reference to temporary [-Wreturn-local-addr] 
    return { 'T', 'E', 'S', 'T' }; 

इस परिस्थिति में सही चेतावनी है? क्या इस तरह के कॉन्स्टेक्स फ़ंक्शन से सरणी को वापस करना गलत है, भले ही फ़ंक्शन को वास्तव में रनटाइम पर कभी नहीं कहा जाता है, केवल संकलन के दौरान?

+1

आप 'उपयोग कर सकते हैं std :: सरणी 'संदर्भ को वापस करने के बजाय, मूल्य से एक constexpr स्थिर सरणी वापस करने के लिए। –

+0

@MikaelPersson धन्यवाद, मैंने एक बिंदु पर std :: array का उपयोग करने का प्रयास किया, लेकिन मेरा पूरा कोड कुछ अजीब चीजें कर रहा है जिसके लिए कॉन्सल-टाइम रूपांतरण को कॉन्स char * की आवश्यकता होती है, और मैं निरंतर में नहीं कर सकता था और [0] अभिव्यक्ति। – Xeno

उत्तर

2

clang 3.4 इस कोड संकलन नहीं करता है के बाद से sum(get_str()) एक constexpr नहीं है और जहाँ तक मैं clang बता सकते हैं सही यहाँ, इस लाइन (see it live) है:

constexpr int s = sum(get_str()); 

निम्न त्रुटि उत्पन्न करता है:

error: constexpr variable 's' must be initialized by a constant expression 
constexpr int s = sum(get_str()); 
      ^ ~~~~~~~~~~~~~~ 

note: read of temporary whose lifetime has ended 
return str[0] + str[1] + str[2] + str[3] 
    ^

यह दो कारणों से वैध constexpr मान्य नहीं है। इस अपरिभाषित व्यवहार का आह्वान करते हैं और इस explicitly disallowed in a constant expressionthe draft C++ standard अनुभाग 5.19 कहते हैं संक्षेप में प्रस्तुत करने के लिए है,:

A conditional-expression e is a core constant expression unless the evaluation of e,

और निम्नलिखित गोली शामिल हैं:

an operation that would have undefined behavior

जो अपने जीवनकाल के बाहर तक पहुँचने होगा। हम जानते हैं कि अस्थायी के जीवनकाल से अनुभाग 12.2अस्थायी वस्तुओं जो कहते हैं कि इस मामले में लागू नहीं होता:

The second context is when a reference is bound to a temporary.117 The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except

और निम्नलिखित गोली में शामिल हैं:

The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not extended; the temporary is destroyed at the end of the full-expression in the return statement.

इसलिए हालांकि यह वास्तव में यह सच है निरंतर अभिव्यक्ति अनुवाद पर मूल्यांकन करने की गारंटी नहीं है, हमारे पास धारा 5.19में एक नोट है निरंतर अभिव्यक्ति जो इसका उल्लेख करता है (जोर मेरा आगे जा रहा):

Note: Constant expressions can be evaluated during translation.—end note ]

यहां तक ​​कि अगर यह हम गारंटी दी गई थी अभी भी अपरिभाषित व्यवहार को लागू करने की अनुमति नहीं दी जाएगी।

दूसरा मुद्दा यह है कि constexpr संदर्भ स्थिर भंडारण अवधि या कार्यों की वस्तुओं के लिए या तो होना चाहिए है, cppreference में यह उल्लेख है इसकी core constant expression section:

Reference constant expression is an lvalue core constant expression that designates an object with static storage duration or a function

और जहाँ तक मैं इस बता सकते हैं के रूप में खंड 5.19 में कवर किया जाता है लगातार भाव पैरा जो कहते हैं:

each non-static data member of reference type refers to an object with static storage duration or to a function,

1

the function is never actually called at runtime, only during compilation?

स्टैंडर्ड द्वारा सभी पर गारंटी नहीं। संकलक रनटाइम पर इसे आमंत्रित करने के अधिकारों के भीतर अच्छी तरह से है।

constexpr अस्थायी कभी मरते हैं यदि संकलक संकलन समय पर इसे आमंत्रित करता है। कंपाइलर कोई दायित्व नहीं है।

+0

यह कोई दायित्व नहीं था, लेकिन यह निश्चित रूप से विधानसभा को देखने के संकलन समय पर किया था। मुझे लगता है कि चेतावनी उचित है हालांकि, और यदि इसकी गारंटी नहीं है तो मैं ऐसा करने से बचूंगा। – Xeno

+0

मुझे पता है कि यह पुराना है, लेकिन मैंने इसे किसी अन्य प्रश्न में देखा और यह यहां प्रासंगिक है: "संकलन समय पर अभिव्यक्तियों का मूल्यांकन करने में सक्षम होने के अलावा, हम ** को संकलित समय पर मूल्यांकन के लिए अभिव्यक्ति की आवश्यकता है; एक परिवर्तनीय परिभाषा के सामने constexpr है कि ** (और का मतलब है): " – Xeno

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