2012-04-29 13 views
22

मैं एक constexpr सूचक कुछ निरंतर पूर्णांक मान के लिए शुरू की घोषणा करने की कोशिश कर रहा हूँ, लेकिन बजना मेरे सभी प्रयास विफल रहा है:Constexpr सूचक मूल्य

प्रयास 1:

constexpr int* x = reinterpret_cast<int*>(0xFF); 

test.cpp:1:20: note: reinterpret_cast is not allowed in a constant expression 

प्रयास 2:

constexpr int* x = (int*)0xFF; 

test.cpp:1:20: note: cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression 

प्रयास 3:

constexpr int* x = (int*)0 + 0xFF; 

test.cpp:1:28: note: cannot perform pointer arithmetic on null pointer 

क्या मैं डिजाइन द्वारा अनुमति नहीं दे रहा हूं? यदि हां, तो क्यों? यदि नहीं, तो मैं इसे कैसे कर सकता हूं?

नोट: जीसीसी इन सभी को स्वीकार करता है।

+2

आपको यहां एक कॉन्स्टेक्सर की आवश्यकता क्यों है? यदि आप फ़ंक्शन का उपयोग नहीं कर रहे हैं तो क्या कॉन्स्टेक्स प्रभावी रूप से कॉन्स के समान नहीं है? –

+0

@RobertMason: ठीक है, उदाहरण के लिए, यदि यह एक वर्ग का स्थिर सदस्य है, और यह constexpr नहीं है, तो मैं इसे ऑनलाइन शुरू नहीं कर सकता। – HighCommander4

+1

शायद एक स्थिर इनलाइन सदस्य फ़ंक्शन डेटा सदस्य से अधिक उपयुक्त होगा। –

उत्तर

18

के रूप में ल्यूक डेंटन नोट्स, अपने प्रयास/2 में [expr.const] नियमों से ब्लॉक किए गए हैं जो कहते हैं कि विभिन्न भाव कोर निरंतर में अनुमति नहीं है भाव, सहित:

- एक reinterpret_cast
- एक ऑपरेशन अपरिभाषित व्यवहार [नोट: [...] कुछ सूचक अंकगणित [...] सहित - अंत टिप्पणी] होता

पहला बुलेट आपके पहले उदाहरण का नियम है। दूसरे उदाहरण ऊपर पहली गोली से की संभावना से इनकार कर रहा है, के साथ साथ [expr.cast] से नियम/4 कि:

रूपांतरण के आधार पर [...] एक reinterpret_cast [...] किया जा सकता है प्रदर्शन किया स्पष्ट प्रकार रूपांतरण के कास्ट नोटेशन का उपयोग कर। वही अर्थपूर्ण प्रतिबंध और व्यवहार लागू होते हैं।

दूसरी गोली WG21 core issue 1313 से जोड़ा है, और स्पष्ट करता है कि एक अशक्त सूचक पर सूचक अंकगणित एक निरंतर अभिव्यक्ति में अनुमति नहीं है किया गया था। यह आपके तीसरे उदाहरण का नियम है।

यहां तक ​​कि अगर इन प्रतिबंधों कोर निरंतर भाव पर लागू नहीं होता, यह अभी भी संभव नहीं एक पूर्णांक कास्टिंग द्वारा उत्पादित एक मूल्य के साथ एक constexpr सूचक प्रारंभ करने में, हो सकता है के बाद से एक constexpr सूचक चर एक पते के निरंतर अभिव्यक्ति द्वारा प्रारंभ किया जाना चाहिए, जो, [expr द्वारा।कॉन्स]/3,

स्थिर संग्रहण अवधि, किसी फ़ंक्शन का पता, या शून्य सूचक मान के साथ किसी ऑब्जेक्ट का पता होना चाहिए।

पॉइंटर प्रकार के लिए एक पूर्णांक कास्ट इनमें से कोई नहीं है।

g ++ अभी तक इन नियमों को सख्ती से लागू नहीं करता है, लेकिन इसकी हालिया रिलीज उनके करीब आ रही हैं, इसलिए हमें यह मानना ​​चाहिए कि यह अंततः उन्हें पूरी तरह कार्यान्वित करेगा।

यदि आपका लक्ष्य एक वैरिएबल घोषित करना है जिसके लिए स्थिर प्रारंभिक प्रदर्शन किया जाता है, तो आप आसानी से constexpr छोड़ सकते हैं - दोनों क्लैंग और जी ++ इस अभिव्यक्ति के लिए एक स्थिर प्रारंभकर्ता उत्सर्जित करेंगे। आप इस अभिव्यक्ति किसी कारण के लिए एक निरंतर अभिव्यक्ति का हिस्सा बनने की जरूरत है, तो आप दो विकल्प हैं: अपने कोड

  • पुनर्गठन ताकि एक intptr_t एक सूचक के बजाय आसपास पारित हो जाता है, और सूचक प्रकार में डाली जब आप (निरंतर अभिव्यक्ति के बाहर) की आवश्यकता है, या
  • __builtin_constant_p((int*)0xFF) ? (int*)0xFF : (int*)0xFF का उपयोग करें। अभिव्यक्ति का यह सटीक रूप (सशर्त ऑपरेटर के बाईं ओर __builtin_constant_p के साथ) सशर्त ऑपरेटर की बाहों में सख्त निरंतर अभिव्यक्ति जांच को अक्षम करता है, और थोड़ा ज्ञात है, लेकिन documented, गैर-पोर्टेबल जीएनयू एक्सटेंशन द्वारा समर्थित दोनों जीसीसी और क्लैंग।
4

कारण यह है कि (एक बार, बहुत उपयोगी) त्रुटि संदेश: reinterpret_cast निरंतर अभिव्यक्ति में अनुमति नहीं है। यह 5.1 9 (अनुच्छेद 2) में स्पष्ट अपवाद में से एक के रूप में सूचीबद्ध है।

reinterpret_cast को सी-स्टाइल कास्ट में बदलना अभी भी reinterpret_cast के अर्थात् समकक्ष के साथ समाप्त होता है, जिससे यह मदद नहीं करता (और फिर संदेश बहुत स्पष्ट है)।

यदि आपके पास मूल्य 0 के साथ सूचक प्राप्त करने का कोई तरीका है तो आप वास्तव में p + 0xff का उपयोग कर सकते हैं लेकिन मैं निरंतर अभिव्यक्ति के साथ ऐसे पॉइंटर को प्राप्त करने का कोई तरीका नहीं सोच सकता। आप अपने सूचकांक पर 0 का मूल्य रखने के साथ शून्य सूचक सूचक (0) जैसे पॉइंटर संदर्भ में या nullptr) पर भरोसा कर सकते थे, लेकिन जैसा कि आपने स्वयं को देखा है, आपका कार्यान्वयन ऐसा करने से इंकार कर देता है। मुझे लगता है कि ऐसा करने की अनुमति है। (उदाहरण के कार्यान्वयन सबसे लगातार भाव के लिए को उबारने के लिए अनुमति दी जाती है।)

+1

और यह '0xff/sizeof (* x) 'होना चाहिए जो वह जोड़ता है। –

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