2014-05-01 10 views
17

कोड टुकड़ाconstexpr सरणी सदस्य समय स्थिरांक संकलित हैं?

struct Parameters { 
    static constexpr int n = 2; 
    static constexpr double v[n] = {4.0, 5.0}; 
}; 

कानूनी सी ++ 11 है? और, यदि हां, तो Parameters::v[0] और Parameters::v[1] संकलन समय स्थिरांक हैं या केवल सूचक Parameters::v स्वयं constexpr (जो भी संकलन समय पर होगा)?

जैसा कि आप देख सकते हैं कि मैं आमतौर पर constexpr सरणी और वर्ग/structs में उनके प्रारंभिकता के बारे में थोड़ा उलझन में हूं। कृपया न केवल मेरे विशिष्ट प्रश्न का उत्तर दें बल्कि इस समस्या से संबंधित सामान्य नुकसान और इस तरह के बारे में भी बताने के लिए स्वतंत्र महसूस करें।

+5

ध्यान दें कि 'v' एक सूचक नहीं है, यह एक सरणी है। – Angew

+0

पूरी तरह से कानूनी लगता है: http://ideone.com/oMwXAj –

+0

संभवतः डुप्लिकेट [\ 'x \ [0 \] == 1 \ 'निरंतर अभिव्यक्ति C++ 11 में जब x const int int \ [\] ?] (http://stackoverflow.com/questions/18903113/x0-1-constant-expression-in-c11-when-x-is-const-int) –

उत्तर

4

मुझे निर्माण के साथ कोई समस्या नहीं दिखती है। का हवाला देते हुए सी ++ 11, [dcl.constexpr]:

§1 constexpr विनिर्देशक केवल एक चर की परिभाषा, एक समारोह या समारोह टेम्पलेट, या एक का एक स्थिर डेटा सदस्य की घोषणा की घोषणा करने के लिए लागू किया जाएगा शाब्दिक प्रकार (3.9)। ...

§9 एक constexpr ऑब्जेक्ट घोषणा में उपयोग किए गए विनिर्देशक वस्तु को const के रूप में घोषित करता है। इस तरह के किसी ऑब्जेक्ट में शाब्दिक प्रकार होगा और इसे प्रारंभ किया जाएगा। यदि इसे किसी कन्स्ट्रक्टर कॉल द्वारा प्रारंभ किया गया है, तो वह कॉल निरंतर अभिव्यक्ति (5.1 9) होगी। अन्यथा, या यदि एक संदर्भ घोषणा में एक कॉन्स्टेक्स विनिर्देशक का उपयोग किया जाता है, तो प्रत्येक प्रारंभिक अभिव्यक्ति में दिखाई देने वाली प्रत्येक पूर्ण अभिव्यक्ति एक निरंतर अभिव्यक्ति होगी। प्रत्येक अंतर्निहित में इस्तेमाल प्रारंभकर्ता भाव और प्रत्येक निर्माता आरंभीकरण के लिए इस्तेमाल किया कॉल परिवर्तित रूपांतरण उन एक निरंतर अभिव्यक्ति (5.19) में अनुमति से एक होगा।

double एक शाब्दिक प्रकार है, और इसलिए शाब्दिक प्रकारों की एक श्रृंखला है। जिसका अर्थ है कि आपके कोड से v[0] और v[1] वास्तव में निरंतर अभिव्यक्तियां हैं।

1
struct Parameters { 
    static constexpr int n = 2; 
    static constexpr double v[n] = {4.0, 5.0}; 
}; 

int main() { 
    constexpr int a = Parameters::v[0]; 
    return 0; 
} 

इस कोड जीसीसी 4.8.2 पर निम्नलिखित में संकलित:

0000000000000000 <main>: 
    0: 55      push rbp 
    1: 48 89 e5    mov rbp,rsp 
    4: c7 45 fc 04 00 00 00 mov DWORD PTR [rbp-0x4],0x4 
    b: b8 00 00 00 00   mov eax,0x0 
    10: 5d      pop rbp 
    11: c3      ret 

तो हाँ, यह एक संकलन समय स्थिर है। फिर

0000000000000000 <main>: 
    0: 55      push rbp 
    1: 48 89 e5    mov rbp,rsp 
    4: b8 00 00 00 00   mov eax,0x0 
    9: c7 45 fc 00 00 00 00 mov DWORD PTR [rbp-0x4],0x0 
    10: c7 45 f8 04 00 00 00 mov DWORD PTR [rbp-0x8],0x4 
    17: 5d      pop rbp 
    18: c3      ret 

, यह एक संकलन समय स्थिर है:

बजना 3.4 समान कोड पैदा करता है।

सब कुछ -O0 के साथ संकलित किया गया था।

पी.एस .: यदि एक घोषित स्थिरांक, तो जीसीसी कुछ भी नहीं परिवर्तन के लिए है, लेकिन बजना करता है के लिए, मान 4 सीधे mov'ed नहीं है के रूप में अगर एक संकलन समय निरंतर था।

तो एक घोषित किया जाता है न स्थिरांक या constexpr तो दोनों compilers पैरामीटर :: वी के इलाज के लिए असफल [0] एक संकलन समय निरंतर रूप में।

2
struct Parameters { 
    static constexpr int n = 2; 
    static constexpr double v[n] = {4.0, 5.0}; 
}; 

यह टुकड़ा अपने आप में निश्चित रूप से जहाँ तक मैं बता सकता हूँ कानूनी है। धारा 7.1.5 [डीसीएल।constexpr] सी ++ 11 मानक के का कहना है कि

constexpr विनिर्देशक केवल करने के लिए ... एक शाब्दिक प्रकार

और एक शाब्दिक प्रकार का एक स्थिर डेटा सदस्य की घोषणा लागू किया जाएगा 3.9 में परिभाषित किया गया है:

एक प्रकार एक शाब्दिक प्रकार है अगर यह होता है:

- एक अदिश प्रकार; या ...

- शाब्दिक प्रकार

की एक सरणी तो static constexpr double v[2] = { ... } निश्चित रूप से वैध जहाँ तक मैं बता सकता है।

चाहे सरणी के सदस्य constexpr हैं ... मुझे यकीन नहीं है। अगर हम

constexpr double d = Parameter::v[1]; 

घोषित तो दोनों जी ++ और बजना यह ठीक संकलन है, लेकिन बजना संस्करण Parameters::v के लिए एक अपरिभाषित संदर्भ के साथ लिंक करने के लिए विफल रहता है। मुझे नहीं पता कि यह क्लैंग बग को इंगित करता है, या क्या निर्माण अमान्य है या नहीं।

+0

तकनीकी रूप से, मुझे नहीं लगता कि सरणी के सदस्य 'constexpr' हो सकते हैं, क्योंकि वे पूर्ण objcets नहीं हैं। लेकिन आप उन्हें सीधे एक्सेस नहीं कर सकते हैं, आप केवल उन्हें 'पैरामीटर्स :: वी [0] '(या' 1') अभिव्यक्ति के माध्यम से प्राप्त कर सकते हैं। और वह निरंतर अभिव्यक्ति की सभी आवश्यकताओं को पूरा करता है। – Angew

+0

@Angew लेकिन व्यावहारिक दृष्टिकोण से, 'पैरामीटर :: v' का पता लिंकर या रनटाइम द्वारा सेट किया जाएगा, और संकलक को ज्ञात नहीं है। तो बेवकूफ, '* (पैरामीटर :: v + 1)' 'constexpr' के रूप में थोड़ा मुश्किल होगा? –

+1

'सी ++ 11 [expr.const] §2,3' लगातार अभिव्यक्तियों पर पुनर्मूल्यांकन परिभाषित करता है, और सरणी dereference उनमें से किसी का उल्लंघन नहीं करता है। तो यह एक निरंतर अभिव्यक्ति है। – Angew

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