एक कॉन्स्ट्रेक्स निर्माता में एक सरणी को इनिशियलाइज़ करने के लिए वैध?


11

निम्नलिखित कोड वैध है?

template <int N>
class foo {
public:
    constexpr foo()
    {
        for (int i = 0; i < N; ++i) {
            v_[i] = i;
        }
    }

private:
    int v_[N];
};

constexpr foo<5> bar;

क्लैंग इसे स्वीकार करता है, लेकिन जीसीसी और एमएसवीसी इसे अस्वीकार करते हैं।

जीसीसी की त्रुटि है:

main.cpp:15:18: error: 'constexpr foo<N>::foo() [with int N = 5]' called in a constant expression
   15 | constexpr foo<5> bar;
      |                  ^~~
main.cpp:4:15: note: 'constexpr foo<N>::foo() [with int N = 5]' is not usable as a 'constexpr' function because:
    4 |     constexpr foo()
      |               ^~~
main.cpp:4:15: error: member 'foo<5>::v_' must be initialized by mem-initializer in 'constexpr' constructor
main.cpp:12:9: note: declared here
   12 |     int v_[N];
      |         ^~

यदि इस तरह का कोड ठीक था, तो मैं index_sequenceएस के कुछ उपयोगों में कटौती कर सकता था ।


1
Gcc10 इसे भी स्वीकार करता है।
गीतयुयनाओ

क्या आप MSVC से त्रुटि ट्रांसक्रिप्ट कर सकते हैं?
अधिकतम

... और जीसीसी, भी।
Evg

1
@songyuanyao - g ++ 10 इसे C ++ 20 का संकलन स्वीकार करते हैं; C ++ 17 या पुराने को संकलित करने से इनकार करता है; ऐसा लगता है कि _vसी + + 17 तक आरंभीकरण सूची में आरंभ किया जाना चाहिए। शायद C ++ 20 में कुछ बदला गया है।
अधिकतम

2
@ ईवीजी वास्तव में दिलचस्प है, क्योंकि यह सुझाव दे सकता है कि क्लैंग अपनी "जागरूकता" का उपयोग करता है कि एक स्थिर-भंडारण-अवधि की वस्तु "कहने के लिए शून्य हो जाती है", यह ऑब्जेक्ट डिफ़ॉल्ट रूप से प्रारंभिक हो सकता है, लेकिन इसके intसदस्य के पढ़े जाने का कभी भी अनुचित व्यवहार नहीं होगा। "। मुझे आश्चर्य है कि क्या जीसीसी ऐसा नहीं कर रहा है जो आज्ञाकारी है, या आसपास का अन्य तरीका ...
लाइटनेस दौड़ ऑर्बिट में

जवाबों:


13

C ++ 20 तक एक constexprसंदर्भ में सामान्य डिफ़ॉल्ट आरंभीकरण निषिद्ध था ।

कारण, मैं अनुमान लगा रहा हूं, यह है कि डिफ़ॉल्ट रूप से प्रारंभिक प्राइमेटिव्स से "गलती से" पढ़ा जाना आसान है, एक ऐसा कार्य जो आपके कार्यक्रम को अपरिभाषित व्यवहार देता है, और अपरिभाषित व्यवहार वाले अभिव्यक्तियाँ सीधे-सीधे निषिद्ध हैं constexpr( रेफ )। भाषा को बढ़ा दिया गया है, ताकि अब एक संकलक को यह जांचना होगा कि क्या इस तरह की रीड होती है और यदि नहीं, तो डिफ़ॉल्ट-आरंभ को स्वीकार किया जाना चाहिए। यह कंपाइलर के लिए थोड़ा अधिक काम है, लेकिन (जैसा कि आपने देखा है!) प्रोग्रामर के लिए पर्याप्त लाभ हैं।

इस पत्र में अपरिभाषित व्यवहार के आह्वान को जारी रखने के लिए निरंतर संदर्भों में तुच्छ रूप से डिफ़ॉल्ट रचनात्मक प्रकारों के लिए डिफ़ॉल्ट आरंभीकरण की अनुमति देने का प्रस्ताव है। संक्षेप में, जब तक कि एकतरफा मानों से पढ़ा नहीं जाता है, तब तक ऐसे राज्यों को ढेर और स्टैक दोनों परिदृश्यों में बाधा के रूप में अनुमति दी जानी चाहिए।

C ++ 20 के बाद से, v_आपके पास "अनइंस्टॉलिज्ड" छोड़ना कानूनी है। फिर आप इसके सभी तत्वों के मूल्यों को निर्दिष्ट करने के लिए आगे बढ़े हैं, जो बहुत अच्छा है।


4
@ max66 मुझे भी! मैंने सभी को विकिपीडिया पर C ++ 20 परिवर्तन सूची को स्कैन किया, कुछ प्रासंगिक पाया constexpr, और लिंक किए गए प्रस्ताव को स्किम किया;)
कक्षा

3
खराब हिस्सा यह है कि 20 साल से अधिक मैं C ++ का उपयोग कर रहा हूं। अगर हर दिन मैं कुछ नया सीखता हूं ... या मैं एक बुरा प्रोग्रामर हूं या C ++ बहुत जटिल हो गया है।
11:66 बजे अधिकतम66

5
@ max66 यह लगभग निश्चित रूप से बाद का है। यह भी तथ्य यह है कि यह मूलभूत रूप से हर दो साल में बदलता रहता है, यह तेजी से आगे बढ़ने का लक्ष्य बनाता है। कौन उस के साथ रख सकते हैं ?! यहां तक ​​कि संकलक भी नहीं रखते हैं।
ऑर्बिट

@ max66 यह पेपर दिमाग में आता है: याद रखें वासा!
Evg

@ ईवीजी ओह, वाह, उस पेपर ने मुझे (IRONY) पास कर दिया था। सटीक!
ऑर्बिट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.