2013-04-06 30 views
20

मैं इस कोडकंपाइलर सोचता है कि "ए (ए और)" एक पल के लिए रावल स्वीकार करता है?

struct A { A(); A(A&); }; 
struct B { B(const A&); }; 

void f(A); 
void f(B); 

int main() { 
    f(A()); 
} 

मेरे आश्चर्य करने के लिए इस जीसीसी और बजना के साथ विफल है। बजना उदाहरण के लिए कहते हैं

Compilation finished with errors: 
source.cpp:8:10: error: no matching constructor for initialization of 'A' 
     f(A()); 
     ^~~ 
source.cpp:1:21: note: candidate constructor not viable: expects an l-value for 1st argument 
    struct A { A(); A(A&); }; 
        ^
source.cpp:1:16: note: candidate constructor not viable: requires 0 arguments, but 1 was provided 
    struct A { A(); A(A&); }; 
      ^
source.cpp:4:13: note: passing argument to parameter here 
    void f(A); 

वे पहली बार f क्यों चयन करते हैं, जब दूसरी f ठीक काम करता है? अगर मैं पहले f को हटा देता हूं, तो कॉल सफल हो जाता है। क्या मेरे लिए अधिक अजीब अगर मैं ब्रेस आरंभीकरण उपयोग करते हैं, यह भी ठीक

int main() { 
    f({A()}); 
} 

वे सभी दूसरे f फोन काम करता है।

उत्तर

17

यह एक भाषा quirk है। पहले f बेहतर मेल खाते हैं क्योंकि आपके A को तर्क प्रकार (A) से मेल खाने के लिए कोई रूपांतरण की आवश्यकता नहीं है, लेकिन जब संकलक कॉल को इस तथ्य को बनाने का प्रयास करता है कि कोई उपयुक्त प्रतिलिपि नहीं मिल सकती है तो कॉल विफल हो जाती है। अधिभार संकल्प चरण निष्पादित करते समय भाषा वास्तविक कॉल की व्यवहार्यता को ध्यान में रखकर अनुमति नहीं देती है।

निकटतम मिलान मानक बोली आईएसओ/आईईसी 14882: 2011 13.3.3.1.2 उपयोगकर्ता-परिभाषित रूपांतरण दृश्यों [over.ics.user]:

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

सूची प्रारंभ मामले के लिए, आप शायद पर देखने की जरूरत है: 13.3.3.1.2 उपयोगकर्ता-परिभाषित रूपांतरण दृश्यों [over.ics.user]

जब गैर कुल वर्ग की वस्तुओं टाइप टी सूची-प्रारंभ कर रहे हैं (8.5.4), अधिभार संकल्प निर्माता दो चरणों में चयन करता है:

- शुरू में, उम्मीदवार कार्यों वर्ग टी के प्रारंभकर्ता-सूची कंस्ट्रक्टर्स (8.5.4) और हैं तर्क सूची में एक गायक के रूप में प्रारंभकर्ता सूची शामिल है ले तर्क

- यदि कोई व्यवहार्य प्रारंभकर्ता-सूची निर्माता पाया जाता है, अधिभार संकल्प फिर से, जहां उम्मीदवार कार्यों वर्ग टी के सभी निर्माणकर्ता और तर्क सूची तत्वों प्रारंभकर्ता सूची के के होते हैं किया जाता है।

यह seqence बाध्य करने के लिए A()A(A&) लेकिन B(const A&) अभी भी व्यवहार्य है की कोशिश कर रहा अस्वीकार करना होगा अधिभार संकल्प f(A) और f(B) के लिए प्रत्येक मामले में व्यवहार्य contructors को देखने के लिए है क्योंकि।

+0

धन्यवाद! मुझे '{...}' मामले के लिए ऐसा कोई नियम नहीं मिल रहा है। क्या यह समझाता है कि '{...}' केस क्यों काम करता है? –

+0

@ जोहान्सचैब-लिटब: मुझे यकीन नहीं है, tbh, आप फ़ंक्शन को _braced-init-list_ के साथ कॉल कर रहे हैं, इसलिए नियम निश्चित रूप से अलग हैं। –

+0

@ जोहान्सचैब-लिटब देखें [over.ics.list]। मुझे लगता है कि [over.ics के साथ क्या करना है।रेफरी]/3 (मैंने पहले आपके कोड को गलत तरीके से पढ़ा था): व्यवहार्य कार्यों के उप-समूह को बनाते समय, ctor 'ए (ए और) 'को व्यवहार्य नहीं माना जाता है क्योंकि यह एक अस्थायी रूप से एक गैर-कॉन्स लैव्यू संदर्भ के लिए बाध्य करता है। – dyp

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