14

निम्नलिखित सी ++ प्रोग्राम सभी compilers में चेतावनी के बिना संकलित द्वारा प्रयोग किया जाता मैं कोशिश की है (जीसीसी 4.6.3, LLVM 3.0, आईसीसी 13.1.1, SolarisStudio 12.1/12.3):विभिन्न कास्टिंग ऑपरेटरों विभिन्न compilers

struct CClass 
{ 
    template<class T> 
    operator T() const { return 1; } 

    operator int() const { return 2; } 
}; 

int main(void) 
{ 
    CClass x; 
    return static_cast<char>(x); 
} 

हालांकि, सोलारिसस्टूडियो कंपेलरों के बदले 2, सोलारिसस्टूडियो (या तो संस्करण) 1 लौटाता है, जिसे मैं सबसे तार्किक परिणाम मानता हूं।

जाहिर लौटने 1.

, इस पता लगाना के बाद से उपयोग करना return x.operator char(); परिणाम सभी compilers में, मैं बाद अंकन का उपयोग किया गया है। हालांकि, मैं जानना चाहता हूं कि कौन से कंपाइलर्स सही हैं और क्यों। (एक यह है कि बहुमत नियम लगता होगा, लेकिन यह अभी भी स्पष्ट नहीं होता क्यों।)

यह सवाल इसलिए सवाल here, here, और here से संबंधित प्रतीत हो रहा है, लेकिन इन "केवल" करने के लिए समाधान दे समस्याएं, कोई स्पष्टीकरण नहीं (कि मैं वैसे भी अपनी विशेष समस्या पर लागू करने में सक्षम था)।

ध्यान दें कि एक अतिरिक्त अधिभारित कास्टिंग ऑपरेटर जोड़ना, operator float() const { return 3; } का परिणाम सॉलारिसस्टूडियो को अस्पष्टता के बारे में शिकायत करने के अलावा सभी कंपाइलरों में परिणाम देता है।

+0

बस मेरे कंपाइलर, जी ++ 4.8.0 में परीक्षण किया गया, और यह 1 लौटाता है। – rodrigo

+1

जी ++ 4.7.2 भी रिटर्न देता है 1. और ऑपरेटर फ्लोट() 'के साथ, किसी भी अस्पष्टता के बारे में कोई शिकायत नहीं है। – hvd

+2

g ++ 4.7 से शुरू होता है http://gcc.godbolt.org/ – Riga

उत्तर

9

पहला (टेम्पलेट) अधिभार चुना जाना चाहिए।

पैरा 13.3.3/C++ 11 स्टैंडर्ड को निर्दिष्ट की 1:

[...] एक व्यवहार्य समारोह F1 एक व्यवहार्य समारोह की तुलना में एक बेहतर कार्य होने के लिए परिभाषित किया गया है F2 अगर सभी तर्कों i के लिए, ICSi(F1)ICSi(F2) से भी बदतर एक रूपांतरण अनुक्रम नहीं है, और उसके बाद

- कुछ तर्क j के लिए, ICSj(F1)तुलना में एक बेहतर रूपांतरण अनुक्रम है 883,210, या, नहीं है कि अगर,

- संदर्भ उपयोगकर्ता परिभाषित रूपांतरण द्वारा एक प्रारंभ है (देखें 8.5, 13.3.1.5, और 13.3.1.6) और की वापसी प्रकार से मानक रूपांतरण अनुक्रम गंतव्य प्रकार (यानी, इकाई के प्रकार प्रारंभ किया जा रहा) गंतव्य प्रकार को F2 की वापसी प्रकार से मानक रूपांतरण अनुक्रम तुलना में एक बेहतर रूपांतरण अनुक्रम है F1।[उदाहरण:

struct A { 
    A(); 
    operator int(); 
    operator double(); 
} a; 
int i = a; // a.operator int() followed by no conversion 
      // is better than a.operator double() followed by 
      // a conversion to int 
float x = a; // ambiguous: both possibilities require conversions, 
      // and neither is better than the other 

- अंत उदाहरण] या, नहीं तो कि,

- F1 एक गैर टेम्पलेट समारोह है और F2 एक समारोह टेम्पलेट विशेषज्ञता है, या, यदि नहीं कि,

[...]

जैसा कि आप देख सकते हैं, तथ्य यह है कि पहला रूपांतरण ऑपरेटर केवल तभी प्रासंगिक हो जाता है जब मानक प्रकार अनुक्रम (char, इस मामले में) गंतव्य प्रकार (char), इस मामले में गैर-टेम्पलेट अधिभार (int) के इस प्रकार में गंतव्य प्रकार (char) के रिटर्न प्रकार से मानक रूपांतरण अनुक्रम से बेहतर)।

हालांकि, char से char करने के लिए एक मानक रूपांतरण, एक सटीक मिलान है, जबकि int से char करने के लिए एक मानक रूपांतरण नहीं है। इसलिए, § 13.3.3/1 का तीसरा आइटम लागू नहीं होता है, और दूसरा आइटम करता है।

इसका मतलब है कि पहला (टेम्पलेट) अधिभार चुना जाना चाहिए।

+0

वास्तव में नहीं। यह कहता है कि उस पर एक टेम्पलेट ** विशेषज्ञता ** उठाया जाएगा। लेकिन ओप के मामले में कोई विशेषज्ञता नहीं है। कंपाइलर एक टेम्पलेट भी शुरू नहीं करेगा, क्योंकि यह पहले से ही एक मिलान गैर-टेम्पलेट कास्ट पाया गया है जिसका उपयोग यह कर सकता है। टेम्पलेट केवल तभी बनाए जाते हैं जब उन्हें स्पष्ट रूप से कहा जाता है, या कोई अन्य मिलान अधिभार नहीं है। कंपाइलर को मिलान करने वाले टेम्पलेट –

+0

@YochaiTimmer पर "अनुमान लगाने" शुरू करने का कोई कारण नहीं है: नहीं, यह सच नहीं है। यह टेम्पलेट को चालू नहीं करेगा, लेकिन यह टेम्पलेट तर्क कटौती करेगा और देखें कि टेम्पलेट ओवरलोड रिज़ॉल्यूशन के लिए एक व्यवहार्य उम्मीदवार है या नहीं। यदि यह * सर्वश्रेष्ठ * व्यावहारिक उम्मीदवार बन जाता है, तो यह इसे उठाएगा और इसे तुरंत चालू करेगा –

5

पहला सटीक मिलान है, दूसरे को रूपांतरण की आवश्यकता है। सटीक मैचों में रूपांतरणों पर प्राथमिकता है।

आपके द्वारा लिंक किए गए अन्य प्रश्न आपके से अधिक संबंधित नहीं हैं।

कुछ सलाह: टेम्पलेट रूपांतरण ऑपरेटरों का उपयोग न करें। इसके बजाय इसे convert_to नाम दें।

+1

+1 एक। शायद आप कुछ स्पष्टीकरण जोड़ सकते हैं कि यह खतरनाक क्यों है। – Walter

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