2016-01-21 11 views
5

के शरीर के भीतर अनियमित संदर्भ में उपयोग किया जाता है कोड का निम्नलिखित भाग सफलतापूर्वक जीसीसी 5.3.0 के साथ संकलित किया गया है लेकिन क्लैंग 3.7.0 के साथ संकलित करने में विफल रहा है। मैंने ऑनलाइन कॉलिरू कंपाइलर्स का उपयोग दोनों मामलों में एक ही कमांड लाइन विकल्पों के साथ किया था: -std = C++ 14 -O2 -Wall -pedantic -pthread।तर्क केवल एक कॉन्स्टेक्स फ़ंक्शन

#include <cstdio> 

// Definition of constexpr function 'foo'. 
constexpr std::size_t foo(const int& arg_foo) { return sizeof(arg_foo); } 

// Definition of function 'test'. 
void test(const int& arg) 
{ 
    // The following line produces an error with clang. 
    constexpr std::size_t res_foo = foo(arg); 

    // Print the result returned by the 'foo' function. 
    std::printf("res_foo = %lu\n", res_foo); 
} 

// Definition of function 'main'. 
int main(int argc, const char* argv[]) 
{ 
    // Test function call. 
    test(argc); 

    // Return statement. 
    return 0; 
} 

बजना निम्न त्रुटि के साथ खारिज कर दिया:

error: constexpr variable 'res_foo' must be initialized by a constant expression 
constexpr size_t res_foo = foo(arg); 
          ~~~~^~~~ 
दो compilers के बीच इस अंतर की वजह से

, मैं अगर यह कोड का एक मान्य टुकड़ा है सोच रहा हूँ। यदि नहीं, तो मैं इस मामले में क्यों बेहतर समझना चाहता हूं।

+0

जीसीसी बग, कई में से एक जब यह constexpr – TemplateRex

+0

@TemplateRex की बात आती है लेकिन किस तरह से 'foo' किसी कॉन्स्टेक्स फ़ंक्शन के नियमों को तोड़ता है? – Archimaredes

+0

@ आर्किमेरेड्स कोई नहीं, त्रुटि यह है कि 'test' में 'arg'' constexpr' – TemplateRex

उत्तर

1

आप const और constexpr मान एक साथ मिश्रण कर रहे हैं। constexpr की परिभाषा एक संकलन समय पर जाना जाता है। लेकिन argc वैरिएबल केवल रन टाइम पर जाना जाता है (यह आपके निष्पादन योग्य को पारित कई तर्क हैं)। तो आप इसे किसी अन्य constexpr चर - res_foo पर असाइन नहीं कर सकते हैं। परिभाषा से constexpr को हटा रहा है परिभाषा आपके कोड को संकलित कर देगी।

const और constexpr के बीच का अंतर कुछ इस तरह करने के लिए सरल किया जा सकता:
const - यह मान संकलन समय और मैं नहीं जा रहा हूँ पर जाना जाता है - मैं इस मूल्य
constexpr बदलने के लिए नहीं जा रहा हूँ इसे बदलने के लिए

मेरा अनुमान है कि जीसीसी इस कोड को ओ 2 के साथ संकलित करने में सक्षम है क्योंकि आप arg_foo तर्क का उपयोग नहीं कर रहे हैं और इसका आकार संकलन समय पर जाना जाता है। लेकिन यह अभी भी वाक्य रचनात्मक रूप से गलत है - संकलक को एक त्रुटि उत्सर्जित करनी चाहिए, क्योंकि गैर-कॉन्टेक्सप्रस मान को कॉन्स्टेक्स चर के लिए असाइन किया गया है।

+1

नहीं है, मुझे लगता है कि उसे इसके बारे में पता है, उसका सवाल यह है क्योंकि वह वास्तव में 'argc' के मान का उपयोग नहीं करता है, वह सिर्फ' आकार लेता है ', जो निरंतर अभिव्यक्ति है। – TartanLlama

+0

@TartanLlama यही कारण है कि जीसीसी इस कोड को ओ 2 के साथ संकलित करने में सक्षम है: यह तर्क को अनदेखा करता है क्योंकि इसका उपयोग नहीं किया जाता है और संकलन समय मूल्य पर एक प्रसिद्ध ज्ञात देता है। लेकिन यह अभी भी वाक्य रचनात्मक रूप से गलत है - संकलक को एक त्रुटि को उत्सर्जित करना चाहिए क्योंकि non-'constexpr' मान को 'constexpr' चर में असाइन किया गया है। – DennisS

+0

मुझे पता है कि यह अभी भी वाक्य रचनात्मक रूप से गलत है, लेकिन मुझे लगता है कि आपको जवाब में संबोधित करना चाहिए। – TartanLlama

0

कार्यक्रम अच्छी तरह से गठित है, क्योंकि foo(arg) सी ++ 14 5.20/2 में परिभाषित एक मूल कोर निरंतर अभिव्यक्ति है। विशेष रूप से, मूल्यांकन के दौरान कोई लालसा-से-रावल्यू रूपांतरण नहीं होता है, जो इसे निरंतर अभिव्यक्ति नहीं बनाता है।

+0

वास्तव में नहीं। मूल्यांकन करना * आईडी-एक्सप्रेशन * 'arg' का मूल्यांकन करने की आवश्यकता है, जो [expr.const]/2.9 से आगे चलाता है: "एक सशर्त अभिव्यक्ति ई कोर निरंतर अभिव्यक्ति है जब तक कि अमूर्त के नियमों का पालन न करें मशीन (1.9), निम्न अभिव्यक्तियों में से एक का मूल्यांकन करेगी: [...] एक आईडी-अभिव्यक्ति जो संदर्भ प्रकार के चर या डेटा सदस्य को संदर्भित करती है जब तक संदर्भ में प्रारंभिक प्रारंभिकता न हो और या तो - यह निरंतर अभिव्यक्ति के साथ प्रारंभ होता है या - यह किसी ऑब्जेक्ट का एक गैर स्थैतिक डेटा सदस्य है जिसका जीवनकाल ई के मूल्यांकन में शुरू हुआ "। –

+0

5/8 "एक अनियमित ऑपरेंड का मूल्यांकन नहीं किया जाता है।" – aschepler

+0

हां, इसका मूल्यांकन 'foo' के अंदर नहीं किया गया है।लेकिन तर्क के गुजरने के लिए इसके बाहर इसका मूल्यांकन किया जाता है। 'Foo (arg) 'का मूल्यांकन करने का पहला चरण' foo' और 'arg' का मूल्यांकन करना है। –

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