टेम्प्लेट और नाम लुकअप को समझने की कोशिश करना


9

मैं निम्नलिखित कोड स्निपेट को समझने की कोशिश कर रहा हूं

स्निपेट # 1

template <typename T>
struct A
{
    static constexpr int VB = T::VD;
};

struct B : A<B>
{
};

न तो gcc9 और न ही clang9 यहां कोई त्रुटि है।

Q. यह कोड क्यों संकलित करता है? A<B>जब हम B से विरासत में हैं, तो क्या हम तत्काल नहीं हैं ? बी में कोई वीडी नहीं है, इसलिए क्या कंपाइलर को यहां त्रुटि नहीं देनी चाहिए?

स्निपेट # 2

template <typename T>
struct A
{
    static constexpr auto AB = T::AD; // <- No member named AD in B
};

struct B : A<B>
{
    static constexpr auto AD = 0xD;
};

इस मामले में, gcc9 ठीक संकलित करता है लेकिन clang9 यह कहते हुए एक त्रुटि फेंकता है कि "AD में B नाम का कोई सदस्य नहीं है"।

प्र। यह gcc9 का संकलन क्यों करता है / यह clang9 के साथ संकलन क्यों नहीं करता है?

स्निपेट # 3

template <typename T>
struct A
{
    using TB = typename T::TD;
};

struct B : A<B>
{
    using TD = int;
};

यहाँ clang9 और gcc9 दोनों त्रुटि देते हैं। gcc9 का कहना है कि "अधूरा टाइप 'स्ट्रक्चर बी' का अवैध उपयोग।"

प्र। यदि यहाँ स्ट्रक्चर बी अधूरा है तो स्निपेट # 2 में अधूरा क्यों है?

संकलक झंडे का इस्तेमाल किया -std=c++17 -O3 -Wall -Werror:। अग्रिम में धन्यवाद!!!


@xception के साथ struct Bतात्कालिकता नहीं है ? AB
म्यूटेबल साइड इफेक्ट

clang9 यह कहते हुए एक त्रुटि फेंकता है कि "B में AD नाम का कोई सदस्य नहीं है" । जैसा Bकि अधूरा है ... लेकिन अनिश्चित जब सदस्य तत्काल होना चाहिए ..
Jarod42

@MutableSideEffect ओह हाँ, मेरा बुरा, एक टेम्पलेट के रूप में अच्छी तरह से पढ़ा है कि :(
xception

@ Jarod42 तो जीसीसी क्यों ठीक संकलन करता है?
म्यूटेबल साइड इफेक्ट

1
मैंने इस प्रश्न को "अधिक ध्यान देने की आवश्यकता" के रूप में चिह्नित किया है और प्रश्न में वास्तव में एक से अधिक प्रश्न हैं (इसलिए मेरा निष्कर्ष), तो मेरा ध्वज गलत क्यों है?
डोमिनिक

जवाबों:


4

मेरा मानना ​​है कि ये अनिवार्य रूप से [temp.inst] / 2 (जोर मेरा) को उबालते हैं :

एक वर्ग टेम्पलेट विशेषज्ञता के अंतर्निहित इन्स्टेन्शियशन घोषणाओं के अंतर्निहित इन्स्टेन्शियशन का कारण बनता है, लेकिन परिभाषाओं की नहीं , डिफ़ॉल्ट तर्क या noexcept-विनिर्देशक के वर्ग के सदस्य काम करता है, सदस्य कक्षाएं, scoped सदस्य enumerations, स्थिर डेटा सदस्यों , सदस्य टेम्पलेट्स, और दोस्त; [...]

और [temp.inst] / 9

जब तक इस तरह के तात्कालिकता की आवश्यकता नहीं होती है, तब कार्यान्वयन एक तात्कालिक डेटा […] एक वर्ग टेम्पलेट के स्थैतिक डेटा सदस्य […] नहीं होगा।

अंतर्निहित टेम्पलेट तात्कालिकता के विषय में मानक में शब्दांकन कई विवरणों को व्याख्या के लिए खुला छोड़ देता है। सामान्य तौर पर, यह मेरे लिए प्रतीत होता है कि आप बस एक टेम्पलेट के कुछ हिस्सों पर भरोसा नहीं कर सकते नहीं instantiated जा रहा है जब तक कि विनिर्देश स्पष्ट रूप से ऐसा कहते हैं। इस प्रकार:

स्निपेट # 1

Q. यह कोड क्यों संकलित करता है? जब हम B से विरासत में आ रहे हैं, तो क्या हम A को तत्काल तैयार नहीं कर रहे हैं? बी में कोई वीडी नहीं है, इसलिए क्या कंपाइलर को यहां त्रुटि नहीं देनी चाहिए?

आप तात्कालिक हैं A<B>। लेकिन A<B>केवल तात्कालिकता घोषणाओं को तात्कालिक बनाती है, न कि इसके स्थैतिक डेटा सदस्यों की परिभाषाओं को। VBकभी भी इस तरह से उपयोग नहीं किया जाता है कि परिभाषा की आवश्यकता होती है। संकलक को इस कोड को स्वीकार करना चाहिए।

स्निपेट # 2

प्र। यह gcc9 का संकलन क्यों करता है / यह clang9 के साथ संकलन क्यों नहीं करता है?

जैसा कि Jarod42 द्वारा बताया गया है, घोषणा ABमें एक प्लेसहोल्डर प्रकार शामिल है। यह मुझे प्रतीत होगा कि मानक का शब्दांकन वास्तव में स्पष्ट नहीं है कि यहां क्या होना चाहिए। क्या स्थैतिक डेटा सदस्य की घोषणा की तात्कालिकता में एक प्लेसहोल्डर प्रकार ट्रिगर प्लेसहोल्डर प्रकार कटौती शामिल है और इस प्रकार, एक उपयोग का गठन होता है जिसे स्थिर डेटा सदस्य की परिभाषा की आवश्यकता होती है? मैं उस मानक में शब्द नहीं खोज सकता जो स्पष्ट रूप से या तो हां या नहीं कहेगा। इस प्रकार, मैं कहूंगा कि दोनों व्याख्याएं समान रूप से यहां मान्य हैं और इस प्रकार, जीसीसी और क्लैंग दोनों सही हैं ...

स्निपेट # 3

प्र। यदि यहाँ स्ट्रक्चर बी अधूरा है तो स्निपेट # 2 में अधूरा क्यों है?

एक वर्ग प्रकार केवल उस बिंदु पर पूरा होता है, जहाँ आप कक्षा-विशेष के समापन }पर पहुँचते हैं [class.mem] / 6 । इस प्रकार, आपके सभी स्निपेट्स में निहित तात्कालिकता के दौरान अधूरा है । यह सिर्फ इतना है कि यह स्निपेट # 1 के लिए अप्रासंगिक था। स्निपेट # 2 में, क्लैंग ने आपको परिणामस्वरूप त्रुटि दी । स्निपेट # 2 के मामले के समान, मुझे इस बात पर ध्यान नहीं दिया जा सकता है कि वास्तव में सदस्य उर्फ ​​घोषणाओं को कब समाप्त किया जाएगा। हालांकि, स्थैतिक डेटा सदस्यों की परिभाषा के विपरीत, वर्ग टेम्पलेट के निहित तात्कालिकता के दौरान सदस्य उर्फ ​​घोषणाओं की तात्कालिकता को स्पष्ट रूप से रोकने के लिए कोई जगह नहीं है। इस प्रकार, मैं कहूंगा कि GCC और दबंग दोनों का व्यवहार इस मामले में मानक की एक वैध व्याख्या है ... BA<B>No member named AD in B


धन्यवाद। इस मामले में, हम शरीर के भीतर स्थिर डेटा सदस्य को इनिशियलाइज़ करते हैं। क्या घोषणा का प्रारंभिक हिस्सा है, या स्थैतिक डेटा सदस्य की परिभाषा का हिस्सा है? मैं इस धारणा में था कि यदि आरंभीकरण शरीर के भीतर है, तो वह स्थैतिक डेटा सदस्य की घोषणा का हिस्सा है। यदि यह घोषणा का हिस्सा है, तो आपकी पहली बोली को क्लास टेम्पलेट के आस-पास निहित तात्कालिकता के हिस्से के रूप में तत्काल तात्कालिकता की आवश्यकता होती है।
जोहान्स शहाब -

मैंने कल्पना में देखा और ऐसा प्रतीत होता है कि यहाँ C ++ 14 और C ++ 17 के बीच अंतर है। C ++ 14 में, constexprस्थैतिक डेटा सदस्य केवल एक घोषणा था। C ++ 17 ने inlineचर प्राप्त किए और constexprइसका अर्थ है inline, और यह इन-बॉडी स्टैटिक डेटा सदस्य घोषणा को एक परिभाषा बनाता है।
जोहान्स शाउब -

eel.is/c++draft/dcl.spec.auto#4.sentence-2 कहता है "किसी प्लेसहोल्डर प्रकार का उपयोग करके घोषित किया गया चर इसके आरंभक से घटाया जाता है। यह प्रयोग एक प्रारंभिक घोषणा ([dcl) में अनुमत है। एक चर का init])। " इसलिए मेरा तर्क है कि स्थिर डेटा सदस्य की परिभाषा की आवश्यकता है, क्योंकि इसमें इनिशलाइज़र शामिल है।
जोहान्स स्काउब -

@ जोहान्सचैब-लिट इस में देखने के लिए धन्यवाद! मैं इन सवालों के बारे में सोच रहा था, लेकिन ऐसा कोई भी शब्द नहीं मिला, जो निर्णायक हो। इनिशियलाइज़ेशन बनाम डेफिनिशन चीज़ के बारे में, क्लास टेम्प्लेट की परिभाषा के अंदर एक सदस्य फ़ंक्शन की परिभाषा पर विचार करें। इस तरह की परिभाषा भी एक घोषणा है और कोई अन्य घोषणाएं नहीं हैं। फिर भी, क्लास टेम्प्लेट के निहित तात्कालिकता केवल एक घोषणा को रोक देगा, लेकिन सदस्य फ़ंक्शन की परिभाषा नहीं। स्थैतिक डेटा सदस्यों के लिए एक ही बात सही क्यों नहीं होगी?
माइकल केन्ज़ेल

अगर कुछ भी नहीं है जो निश्चितता की आवश्यकता है, तो परिभाषा को त्वरित नहीं किया गया है। लेकिन autoमामले में, नियम का कहना है कि घोषणा एक प्रारंभिक घोषणा होनी चाहिए। यह केवल तभी हो सकता है जब यह ज्ञात हो कि घोषणा एक परिभाषा है (जहाँ तक मुझे पता है .. मैं थोड़ी देर के लिए वकील-भूमि से बाहर आया हूँ)। अतीत में, इसी तरह का एक मामला था और eel.is/c++draft/temp.inst#2.sentence-3 जोड़ा गया था, जहां एक घोषणा है कि एक परिभाषा का तात्कालिक रूप से "एक परिभाषा के रूप में जाना जा रहा है" बिना वास्तव में है। तात्कालिकता की परिभाषा।
जोहान्स शाउब -
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.