11

निम्नलिखित कोड में कौन सा कन्स्ट्रक्टर कहा जाना चाहिए और क्यों?डबल ब्रेस प्रारंभिकरण

struct S 
{ 
    int i; 
    S() = default; 
    S(void *) : i{1} { ; } 
}; 

S s{{}}; 

अगर मैं clang का उपयोग करें (ट्रंक से), तो दूसरा एक कहा जाता है।

यदि दूसरे कन्स्ट्रक्टर को टिप्पणी की जाती है, तो S{{}} अभी भी मान्य अभिव्यक्ति है, लेकिन (मुझे विश्वास है) S{} के डिफ़ॉल्ट-निर्मित उदाहरण से चालक-निर्माता को मामले में बुलाया जाता है।

रूपांतरण निर्माता को पहले मामले में डिफ़ॉल्ट पर प्राथमिकता क्यों है?

S के निर्माताओं की इस तरह के एक संयोजन के इरादे मामलों में, जब यह एक निश्चित तरीके से प्रारंभ किया जाना चाहिए की एक परिमित सेट को छोड़कर, अपने std::is_trivially_default_constructible_v<S> संपत्ति को बचाने के लिए है।

+0

"* यदि दूसरा कन्स्ट्रक्टर टिप्पणी की जाती है, तो एस {{}} अभी भी वैध अभिव्यक्ति है, लेकिन (मुझे यकीन है) एस-} के डिफ़ॉल्ट-निर्मित उदाहरण से चालक-निर्माता को मामले में बुलाया जाता है। *" नहीं , यह कुल-प्रारंभिक 'एस' को एक ब्रेस-इनिटेड' int' के साथ प्रारंभ करता है। – ildjarn

+0

@ildjarn सवाल अभी भी लागू है। – Orient

उत्तर

9

यदि दूसरे निर्माता को टिप्पणी की जाती है, तो एस {{}} अभी भी वैध अभिव्यक्ति है, लेकिन (मुझे यकीन है) एस-} के डिफ़ॉल्ट-निर्मित उदाहरण से चालक-निर्माता को मामले में बुलाया जाता है।

वास्तव में, ऐसा नहीं होता है। [Dcl.init.list] में आदेश है:

एक वस्तु या प्रकार टी के संदर्भ की सूची-प्रारंभ इस प्रकार परिभाषित किया गया है:
- अगर टी एक समग्र वर्ग है और प्रारंभकर्ता सूची एक भी नहीं है प्रकार सीवी यू का तत्व, [...]
- अन्यथा, यदि टी एक वर्ण सरणी है और [...]
- अन्यथा, यदि टी कुल है, तो कुल प्रारंभिक (8.6.1) किया जाता है।

एक बार जब आप S(void *) निर्माता निकालने के लिए, S एक समग्र हो जाता है - यह कोई उपयोगकर्ता द्वारा प्रदान की निर्माता है। S() = default उपयोगकर्ता द्वारा प्रदान किए गए कारणों के रूप में नहीं गिना जाता है क्योंकि कारण। {} से कुल प्रारंभिकरण i सदस्य को मूल्य-प्रारंभ करने के लिए समाप्त होगा।


क्यों रूपांतरण निर्माता डिफ़ॉल्ट बहुत पहले मामले में एक से अधिक प्राथमिकता है? अन्यथा, एक विशेषज्ञता है, तो टी है - अगर प्रारंभकर्ता सूची [...]
कोई तत्व है अन्यथा, -

:

void* शेष के साथ

, चलो बुलेट सूची नीचे जा रहा रखने दें std :: startizer_list, [...]
- अन्यथा, यदि टी एक वर्ग प्रकार है, तो रचनाकारों पर विचार किया जाता है। लागू कन्स्ट्रक्टर का अनुमान लगाया गया है और सबसे अच्छा अधिभार संकल्प (13.3, 13.3.1.7) के माध्यम से चुना जाता है।

[over.match.list] हमें एक दो चरण अधिभार संकल्प प्रक्रिया देता है:

- शुरू में, उम्मीदवार कार्यों प्रारंभकर्ता-सूची कंस्ट्रक्टर्स (8.6 कर रहे हैं।4) कक्षा टी और तर्क सूची में प्रारंभिक सूची को एक तर्क के रूप में शामिल किया गया है।
- यदि कोई व्यवहार्य प्रारंभकर्ता-सूची निर्माता नहीं मिला है, तो ओवरलोड रिज़ॉल्यूशन फिर से किया जाता है, जहां उम्मीदवार फ़ंक्शन कक्षा टी के सभी निर्माता हैं और तर्क सूची में प्रारंभकर्ता सूची के तत्व शामिल हैं।

यदि प्रारंभकर्ता सूची में कोई तत्व नहीं है और टी का डिफॉल्ट कन्स्ट्रक्टर है, तो पहला चरण छोड़ा गया है।

S किसी भी प्रारंभकर्ता सूची कंस्ट्रक्टर्स नहीं है, तो हम दूसरी गोली में जाकर {} का तर्क सूची के साथ सभी निर्माताओं की गणना। ,

अन्यथा यदि पैरामीटर एक गैर-कुल दसवीं और अधिभार 13.3 प्रति संकल्प है:

S(S const&); 
S(S&&); 
S(void *); 

रूपांतरण दृश्यों [over.ics.list] में परिभाषित कर रहे हैं: हम कई व्यवहार्य कंस्ट्रक्टर्स है .1.7 एक एक्स का सर्वोत्तम कन्स्ट्रक्टर सी चुनता है जो तर्क प्रारंभकर्ता सूची से टाइप एक्स के ऑब्जेक्ट को प्रारंभ करने के लिए करता है:
- यदि सी प्रारंभिक-सूची निर्माता नहीं है और प्रारंभकर्ता सूची में cv प्रकार का एक तत्व है यू, [...] - अन्यथा, निहित रूपांतरण अनुक्रम एक है दूसरे मानक रूपांतरण अनुक्रम के साथ उपयोगकर्ता परिभाषित रूपांतरण अनुक्रम एक पहचान रूपांतरण

और

अन्यथा, यदि पैरामीटर प्रकार एक श्रेणी नहीं है: [...] - अगर प्रारंभकर्ता सूची कोई तत्व है, अंतर्निहित रूपांतरण अनुक्रम पहचान रूपांतरण है।

है, S(S&&) और S(S const&) कंस्ट्रक्टर्स दोनों उपयोगकर्ता परिभाषित रूपांतरण दृश्यों के साथ साथ पहचान रूपांतरण कर रहे हैं। लेकिन S(void *) सिर्फ एक पहचान रूपांतरण है।

लेकिन, [over.best.ics] इस अतिरिक्त नियम है:

हालांकि, अगर लक्ष्य
है - एक निर्माता या
के पहले पैरामीटर - के अंतर्निहित वस्तु पैरामीटर 13.3.1.3, जब [...]
- - 13.3.1.4, 13.3.1.5, या 13.3.1.6 (उपयोगकर्ता-निर्धारित रूपांतरण समारोह
और निर्माता या उपयोगकर्ता-निर्धारित रूपांतरण समारोह
द्वारा एक उम्मीदवार है सभी मामलों में), या
- 13.3.1.7 का दूसरा चरण जब प्रारंभकर्ता सूची में एक तत्व है जो स्वयं एक प्रारंभिक सूची है, और लक्ष्य X वर्ग के निर्माता का पहला पैरामीटर है, और रूपांतरण X या संदर्भ है (संभवतः सीवी-योग्य) X,

उपयोगकर्ता परिभाषित रूपांतरण अनुक्रमों पर विचार नहीं किया जाता है।

इस उम्मीदवार के रूप में विचार S(S const&) और S(S&&) से शामिल नहीं है - वे ठीक इस मामले हैं - लक्ष्य [over.match.list] के दूसरे चरण और लक्ष्य की वजह से निर्माता की पहली पैरामीटर जा रहा है संभावित रूप से सीवी-योग्य S का संदर्भ होने के नाते, और ऐसा रूपांतरण अनुक्रम उपयोगकर्ता परिभाषित किया जाएगा।

इसलिए, शेष शेष उम्मीदवार S(void *) है, इसलिए यह मामूली व्यवहार्य उम्मीदवार है।

+0

@ टी.सी. मुझे लगता है कि मुझे यकीन नहीं था कि दूसरा एक मानक रूपांतरण अनुक्रम था या नहीं। पहला स्पष्ट रूप से उपयोगकर्ता द्वारा परिभाषित किया गया है ... – Barry

+3

आपका विश्लेषण थोड़ा विस्तार के अलावा सही है: 16.3.3.1 [over.best.ics] p4 "और कन्स्ट्रक्टर या उपयोगकर्ता के कारण चाल और प्रतिलिपि निर्माता व्यवहार्य नहीं हैं - निर्धारित रूपांतरण फ़ंक्शन एक उम्मीदवार है ... [over.match.list] का दूसरा चरण जब प्रारंभकर्ता सूची में एक तत्व है जो स्वयं प्रारंभकर्ता सूची है, और लक्ष्य कक्षा X के निर्माता का पहला पैरामीटर है , और रूपांतरण एक्स या सीवी एक्स के संदर्भ में है ... उपयोगकर्ता द्वारा परिभाषित रूपांतरण अनुक्रमों पर विचार नहीं किया जाता है। " –

+0

जब उपयोगकर्ता द्वारा प्रदान किए गए कन्स्ट्रक्टर को हटा दिया गया था (उदाहरण के लिए डिफ़ॉल्ट-कन्स्ट्रक्टर की परिभाषा को वर्तनी करके) यह कुल मिलाकर नहीं था, तो रूपांतरण कन्स्ट्रक्टर के साथ उसका उदाहरण अब संकलित नहीं होगा। –

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