C ++ 17 इनलाइन चर का परिचय देता है
C ++ 17 constexpr static
सदस्य चर के लिए इस समस्या को हल करता है, अगर यह ओड-यूज़ होती है तो आउट-ऑफ-लाइन परिभाषा की आवश्यकता होती है। प्री-सी ++ 17 विवरण के लिए इस उत्तर का दूसरा भाग देखें।
प्रस्ताव P0386 इनलाइन चर लागू करने की क्षमता का परिचय inline
विनिर्देशक चर करने के लिए। इस मामले के लिए विशेष रूप से constexpr
संकेत मिलता है inline
स्थिर सदस्य चर के लिए। प्रस्ताव कहता है:
इनलाइन विनिर्देशक को चर के साथ-साथ कार्यों पर भी लागू किया जा सकता है। एक वैरिएबल घोषित इनलाइन में एक फ़ंक्शन के रूप में एक ही शब्दार्थ होता है इनलाइन घोषित: इसे परिभाषित किया जा सकता है, पहचान के अनुसार, एकाधिक अनुवाद इकाइयों में, हर अनुवाद इकाई में इसे परिभाषित किया जाना चाहिए, जिसमें इसका उपयोग किया जाता है, और कार्यक्रम का व्यवहार इस प्रकार है बिल्कुल एक चर है।
और संशोधित [basic.def] P2:
एक घोषणा एक परिभाषा है जब तक
...
- यह एक वर्ग परिभाषा के बाहर एक स्थैतिक डेटा सदस्य की घोषणा करता है और वैरिएबल को क्लास के भीतर कॉन्स्टैक्सप्रो स्पेसिफ़ायर के साथ परिभाषित किया गया था (यह उपयोग पदावनत है; देखें [depr.static_constexpr]),
...
और [depr.static_constexpr] जोड़ें :
पूर्व C ++ अंतर्राष्ट्रीय मानकों के साथ अनुकूलता के लिए, एक स्थिर स्थैतिक डेटा सदस्य को बिना किसी इनिशियलाइज़र के साथ कक्षा से बाहर redeclared किया जा सकता है। यह उपयोग पदावनत है। [ उदाहरण:
struct A {
static constexpr int n = 5; // definition (declaration in C++ 2014)
};
constexpr int A::n; // redundant declaration (definition in C++ 2014)
- अंतिम उदाहरण]
C ++ 14 और पहले का
C ++ 03 में, हमें केवल const integrals या const enumeration type के लिए इन-क्लास इनिशियलाइज़र प्रदान करने की अनुमति दी गई थी , C ++ 11 में इसका उपयोग शाब्दिक प्रकारोंconstexpr
तक बढ़ाया गया था ।
C ++ 11 में, हमें स्थैतिक constexpr
सदस्य के लिए नेमस्पेस स्कोप परिभाषा प्रदान करने की आवश्यकता नहीं है यदि यह odr-used नहीं है , तो हम इसे C ++ 11 मानक सेक्शन 9.4.2
[class.static.data] के मसौदे से देख सकते हैं, जो कहता है ( जोर मेरा आगे जा रहा है ):
[...] शाब्दिक प्रकार के एक स्थैतिक डेटा सदस्य को कॉन्स्ट्रेक्स स्पेसियर के साथ वर्ग परिभाषा में घोषित किया जा सकता है; यदि ऐसा है, तो इसकी घोषणा एक ब्रेस-या-सम-इनिशलाइज़र निर्दिष्ट करेगी जिसमें प्रत्येक इनिशियलाइज़र-क्लॉज जो एक असाइनमेंट-एक्सप्रेशन है, एक स्थिर अभिव्यक्ति है। [नोट: इन दोनों मामलों में, सदस्य निरंतर अभिव्यक्तियों में दिखाई दे सकता है। -एंड नोट]
यदि प्रोग्राम में ओड-यूज़ेड (3.2) है तो सदस्य को नेमस्पेस स्कोप में परिभाषित किया जाएगा और नेमस्पेस स्कोप परिभाषा में इनिशियलाइज़र नहीं होगा।
तो फिर सवाल बन जाता है, क्या यहां baz
ओआरआर का उपयोग किया जाता है:
std::string str(baz);
और इसका उत्तर हां है , और इसलिए हमें नाम स्थान की परिभाषा की भी आवश्यकता है।
तो हम कैसे निर्धारित करते हैं कि एक चर का उपयोग किया जाता है ? अनुभाग में मूल C ++ 11 3.2
शब्दांकन [basic.def.odr] कहता है:
एक अभिव्यक्ति का मूल्यांकन संभावित रूप से तब तक किया जाता है जब तक कि यह एक अविकसित ऑपरेंड (क्लॉज 5) या उसके उपपरिवर्तन न हो। एक चर जिसका नाम एक संभावित मूल्यांकन अभिव्यक्ति के रूप में प्रकट होता है, जब तक कि
यह एक ऐसी वस्तु न हो, जब तक कि यह एक ऐसी वस्तु न हो जो एक स्थिर अभिव्यक्ति (5.19) में प्रकट होने के लिए आवश्यकताओं को संतुष्ट करती है और लैवल्यू-टू-रेवल्यू रूपांतरण (4.1) को तुरंत लागू किया जाता है ।
तो baz
एक निरंतर अभिव्यक्ति उत्पन्न करता है लेकिन अंतराल-से-अंतराल रूपांतरण तुरंत लागू नहीं होता है क्योंकि यह baz
एक सरणी होने के कारण लागू नहीं होता है । यह खंड 4.1
[conv.lval] में शामिल है जो कहता है:
एक गैर-फ़ंक्शन, गैर-सरणी प्रकार टी का एक चमक (3.10) एक प्रचलन 5। 3 में परिवर्तित किया जा सकता है [...]
सरणी-से-पॉइंटर रूपांतरण में क्या लागू किया जाता है ।
[Basic.def.odr] का यह शब्द दोष रिपोर्ट 712 के कारण बदल दिया गया था क्योंकि कुछ मामले इस शब्दांकन द्वारा कवर नहीं किए गए थे लेकिन ये परिवर्तन इस मामले के परिणामों को नहीं बदलते हैं।