मेरी कक्षा गैर-डिफ़ॉल्ट क्यों है?


28

मेरे पास वे कक्षाएं हैं:

#include <type_traits>

template <typename T>
class A {
public:
    static_assert(std::is_default_constructible_v<T>);

};

struct B {
   struct C {
      int i = 0;
   };

    A<C> a_m;
};

int main() {
    A<B::C> a;
}

संकलन करते समय, a_mडिफ़ॉल्ट रूप से रचनात्मक नहीं है , लेकिन aहै।

जब बदल रहा Cहै:

struct C {
      int i;
   };

सब कुछ ठीक है।

क्लैंग 9.0.0 के साथ परीक्षण किया गया।


3
जीसीसी 8.3 - ठीक है, जीसीसी 9.1 / 9.2 - विफल।
Evg

2
इसके साथ C() {}भी काम करता है।
Evg

3
यह मेरे लिए छोटी गाड़ी बदबू आ रही है। बगज़िला पर तुरंत कोई स्पष्ट मैच नहीं।
कक्षा

2
दिलचस्प: static_assertमें Aविफल रहता है, लेकिन अगर आप के बजाय डिफ़ॉल्ट निर्माण एक Tके अंदर A(जैसे एक सदस्य डाल T t;वहाँ), यह सब ठीक काम करता है। प्रकार लक्षण आपको बता रहा है और वास्तव में क्या संभव है के बीच एक असंगतता ...
sebrockm

2
@ नोइकोल्स ट्रू, लेकिन ऐसा इसलिए है क्योंकि कुछ किनारे के मामले, जिनमें से कोई भी यहां लागू नहीं होता है (विशेष रूप से, जैसा कि cepreference पर एक ही वाक्य कहता है, const int x;एक शुरुआती के बिना अमान्य है, विशुद्ध रूप constसे अंतर्निहित और प्रकारों और कुछ के प्रारंभिक व्यवहार के कारण है इतिहास)
लाइटनेस दौड़ ऑर्बिट में

जवाबों:


9

यह मानक के पाठ और टिप्पणियों में नोट किए गए कई प्रमुख कार्यान्वयनों द्वारा दोनों को अस्वीकृत कर दिया गया है, लेकिन पूरी तरह से असंबंधित कारणों के लिए।

सबसे पहले, "पुस्तक द्वारा" कारण: की तात्कालिकता का बिंदु A<C>, मानक के अनुसार, परिभाषा के तुरंत पहलेB , और std::is_default_constructible<C>तात्कालिकता का बिंदु इसके तुरंत पहले है:

एक वर्ग टेम्पलेट विशेषज्ञता के लिए, [...] यदि विशेषज्ञता का तात्कालिक रूप से तात्कालिक उपयोग किया जाता है, क्योंकि इसे किसी अन्य टेम्पलेट विशेषज्ञता के भीतर से संदर्भित किया जाता है, यदि संदर्भ जिस संदर्भ से निर्दिष्ट किया जाता है, वह टेम्पलेट पैरामीटर पर निर्भर करता है, और यदि विशेषज्ञता पहले से त्वरित नहीं है। एन्क्लोजिंग टेम्पलेट के तात्कालिकता के लिए, तात्कालिकता का बिंदु संलग्नक टेम्पलेट के तात्कालिकता के बिंदु से पहले है। अन्यथा, इस तरह के एक विशेषज्ञता के लिए तात्कालिकता तुरंत नामस्थान गुंजाइश घोषणा या परिभाषा है कि विशेषज्ञता के लिए संदर्भित करता है।

चूँकि Cउस बिंदु पर स्पष्ट रूप से अपूर्णता है, तात्कालिकता std::is_default_constructible<C>का व्यवहार अपरिभाषित है। हालाँकि, कोर मुद्दा 287 देखें , जो इस नियम को बदल देगा।


वास्तव में, यह एनएसडीएमआई के साथ करना है।

  • NSDMI अजीब हैं क्योंकि उन्हें पार्स करने में देरी हो जाती है - या मानक समानता में वे "पूर्ण-श्रेणी का संदर्भ" हैं।
  • इस प्रकार, यह = 0सिद्धांत रूप में Bअभी तक घोषित नहीं की गई चीजों का संदर्भ दे सकता है , इसलिए कार्यान्वयन वास्तव में इसे पार्स करने की कोशिश नहीं कर सकता है जब तक कि यह समाप्त नहीं हुआ है B
  • एक वर्ग को पूरा करने के लिए विशेष सदस्य कार्यों के निहित घोषणा की आवश्यकता होती है, विशेष रूप से डिफ़ॉल्ट निर्माता में, क्योंकि Cएक निर्माता घोषित नहीं होता है।
  • उस घोषणा के कुछ हिस्सों (कॉन्स्ट्रेप-नेस, नोएक्ससेप्ट-नेस) एनएसडीएमआई के गुणों पर निर्भर करते हैं।
  • इस प्रकार, यदि कंपाइलर NSDMI को पार्स नहीं कर सकता है, तो यह क्लास को पूरा नहीं कर सकता है।
  • नतीजतन, उस बिंदु पर जब यह तात्कालिकता करता है A<C>, यह सोचता है कि Cअधूरा है।

विलंबित पार्स क्षेत्रों से निपटने वाला यह पूरा क्षेत्र कार्यान्वयन अधिमिश्रण के साथ, बहुत ही कम है। इसे साफ होने में कुछ समय लग सकता है।


0

अपरिभाषित व्यवहार यह है:

यदि ऊपर दिए गए टेम्पलेट का एक तात्कालिकता निर्भर करता है, सीधे या परोक्ष रूप से, एक अपूर्ण प्रकार पर, और वह तात्कालिकता एक अलग परिणाम दे सकती है यदि उस प्रकार को काल्पनिक रूप से पूरा किया गया था, तो व्यवहार अपरिभाषित है।


7
C अपूर्ण क्यों है?
अंतरजाल

1
@interjay, Cपूर्ण है, लेकिन Bनहीं है। और B::Cअप्रत्यक्ष रूप से निर्भर करता है B
Evg

1
@ ईवीजी पाठ "सीधे या परोक्ष रूप से निर्भर करता है" केवल cppreference.com पर दिखाई देता है। मानक बस कहता है कि टाइप टी को पूरा करने की आवश्यकता है।
इंटरजय


2
@interjay मैंने सबसे अधिक इस शब्द को लिखा। हम जो कहने की कोशिश कर रहे हैं, वह यह है कि 1) यदि आप एक तरह से एक लक्षण का पता लगाते हैं जो बाद में ओडीआर उल्लंघन को भड़का सकता है जब कुछ अधूरा प्रकार पूरा हो जाता है, तो यह अपरिभाषित है; और 2) यह अपरिभाषित है भले ही आप वास्तव में अपने कार्यक्रम में एक ओडीआर उल्लंघन का कारण नहीं बनते हैं, ताकि मानक पुस्तकालय कार्यान्वयन निदान करना चुन सकें कि बिंदु पर लक्षण का उपयोग किया जाता है यदि वे इतनी इच्छा रखते हैं। यदि Cकुछ अजीब SFINAE के साथ एक डिफ़ॉल्ट कंस्ट्रक्टर टेम्पलेट है जो Bअलग-अलग तरीके से पूरा होने पर उत्तर बदल सकता है, तो यकीन है, विशेषता इस पर निर्भर करती है।
टीसी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.