2017-12-20 113 views
12

इस कोड में अभिव्यक्ति b एक कोर निरंतर अभिव्यक्तियह अभिव्यक्ति निरंतर अभिव्यक्ति क्यों नहीं है?

int main() 
{ 
    constexpr int a = 10; 
    const int &b = a; 
    constexpr int c = b; // here 
    return 0; 
} 

के बाद से मानक कहते हैं (8.20, पैरा 2 [expr.const] n4700 में)

कोई व्यंजक e है किया जाएगा कोर निरंतर अभिव्यक्ति जब तक e का मूल्यांकन निम्न अभिव्यक्तियों में से एक का मूल्यांकन करेगा:

  • ...

  • एक lvalue करने वाली rvalue रूपांतरण (7.1) जब तक यह

    • लिए आवेदन किया है ...

    • एक गैर अस्थिर glvalue जो को संदर्भित करता है जो एक गैर-अस्थिर वस्तु है जो कॉन्स्टेक्स के साथ परिभाषित किया गया है, या जो इस तरह के ओ-म्यूटेबल सबोबजेक्ट को संदर्भित करता है bject, या

पहले, उपरोक्त कोड में अभिव्यक्ति b एक lvalue (जो भी एक glvalue है) के बाद से यह एक संदर्भ है, जिससे एक चर (8.1.4.1, अनुच्छेद 1 की जा रही है [expr.prim.id.unqual]):

अभिव्यक्ति एक lvalue यदि इकाई एक समारोह, चर, या डेटा के सदस्य और एक prvalue अन्यथा है; यदि पहचानकर्ता थोड़ा-क्षेत्र (11.5) निर्दिष्ट करता है तो यह थोड़ा सा क्षेत्र है।

दूसरा, वस्तु चर b को दर्शाता है a है, और यह constexpr साथ घोषित की गई। हालांकि, जीसीसी शिकायत

./hello.cpp: In function ‘int main()’: 
./hello.cpp:6:20: error: the value of ‘b’ is not usable in a constant expression 
    constexpr int c = b; 
        ^
./hello.cpp:5:13: note: ‘b’ was not declared ‘constexpr’ 
    const int &b = a; 

जहां तक ​​मेरा बता सकते हैं, एक संदर्भ एक वस्तु नहीं है, तो ऊपर गोली जाहिरा तौर पर पता चलता है कि aconstexpr के साथ घोषित किया जाएगा। क्या मैं कुछ भूल रहा हूँ? जीसीसी के साथ मैं सहमत नहीं हूं कि जीसीसी b को एक ऑब्जेक्ट के रूप में देखता है, जिसके लिए इसे constexpr के साथ घोषित करने की आवश्यकता होती है। हालांकि, b एक वस्तु नहीं है!

+1

क्लैंग जीसीसी के साथ सहमत है। लेकिन मुझे लगता है कि मैं आपसे सहमत हूं, यह मानक या कंपाइलरों में एक दोष है। यह भी ध्यान में है कि एमएसवीसी कोड स्वीकार करता है। –

उत्तर

12

कोर निरंतर भाव के लिए नियमों में से एक यह है कि हम can't evaluate:

एक आईडी अभिव्यक्ति जब तक संदर्भ एक पूर्ववर्ती आरंभीकरण और या तो

है कि संदर्भ प्रकार का एक चर या डेटा सदस्य को संदर्भित करता है
  • यह एक निरंतर अभिव्यक्ति या
  • अपने जीवनकाल के साथ आरंभ नहीं हो जाता ई के मूल्यांकन के भीतर शुरू किया;

b एक आईडी अभिव्यक्ति कि प्रारंभ से ठीक पहले के साथ संदर्भ प्रकार का एक चर के लिए संदर्भित करता है। हालांकि, इसे a से शुरू किया गया है। a एक निरंतर अभिव्यक्ति है? [expr.const]/6 से:

एक निरंतर अभिव्यक्ति या तो एक glvalue कोर निरंतर अभिव्यक्ति है कि एक इकाई के एक निरंतर अभिव्यक्ति का एक अनुमति दी परिणाम है कि को संदर्भित करता है (जैसा कि नीचे वर्णित), या एक prvalue कोर निरंतर अभिव्यक्ति जिसका मान को संतुष्ट करता है निम्नलिखित की कमी: [...]

एक इकाई एक निरंतर अभिव्यक्ति के अनुमति दी परिणाम है अगर यह स्थिर भंडारण अवधि है कि या तो नहीं एक अस्थायी वस्तु है या एक अस्थायी वस्तु जिसका मान को संतुष्ट करता है के साथ एक वस्तु है उपरोक्त बाधाओं, या यह एक समारोह है।

a, एक glvalue कोर निरंतर अभिव्यक्ति (यह expr.const/2 में प्रतिबंध के किसी भी हिट नहीं करता) है, लेकिन यह है नहीं स्थिर भंडारण अवधि के साथ एक वस्तु। न ही यह एक समारोह है।

इसलिए, a निरंतर अभिव्यक्ति नहीं है। और b, परिणामस्वरूप, निरंतर अभिव्यक्ति से प्रारंभ नहीं किया गया है और इसलिए कोर निरंतर अभिव्यक्ति में उपयोग नहीं किया जा सकता है। और इस प्रकार c की शुरुआत निरंतर अभिव्यक्ति नहीं होने के कारण बीमार है। a को static constexpr int के रूप में घोषित करें, और दोनों जीसीसी और क्लैंग कार्यक्रम को स्वीकार करते हैं।

सी ++, आप जादुई जानवर।

+2

'बी' को एक glvalue के साथ शुरू किया गया है, और **' a' एक glvalue के रूप में ** निरंतर अभिव्यक्ति नहीं है। – cpplearner

+0

@cpplearner क्या, क्यों? – Barry

+0

वास्तव में, ध्यान दें कि क्लैंग भी संकलित करने से इंकार कर देता है "constexpr int const & b = a;" "ए 'का संदर्भ' निरंतर अभिव्यक्ति नहीं है" ... –

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