2011-06-23 12 views
7

पर पॉइंटर लेने वाले फ़ंक्शन पर टेम्पलेट फ़ंक्शन पर जाता है। निम्नलिखित कोड g ++ 4.1.2 और g ++ 4.4.4 पर संकलित किया गया था। दोनों टिप्पणियों में दिए गए परिणाम देते हैं।एक गैर-कॉन्स्ट पॉइंटर वाला फ़ंक्शन कॉल करना

int f(const int * a) 
{ 
    return 0; 
} 

template<typename A> 
int f(A a) 
{ 
    return 1; 
} 

int main() 
{ 
    int x; 
    // return f(&x); // returns 1 
    return f((const int *)&x); // returns 0 
} 

यह f(int *) की एक कॉल करने के लिए नीचे उबालने के लिए प्रकट होता है f<int *>(int *) बजाय उम्मीद f(const int *) को हल करता है। मुझे यह चौंकाने वाला और पूरी तरह से अनजान मिला।

क्या यह जी ++ में एक बग है, सी ++ का एक अंधेरा कोने, या किसी कारण से स्पष्ट है कि मुझे याद आ रही है? यदि यह एक बग नहीं है, तो इसके पीछे सिद्धांत या तर्क क्या है? क्या इस मुद्दे के बारे में कोई सुरक्षित प्रथा है?

+0

'एफ (इंट)' और 'एफ (कॉन्स इंट)' समान प्रोटोटाइप हैं जहां तक ​​एएनएसआई सी ++ कंपाइलर – sehe

+1

से संबंधित है, लेकिन 'एफ (int *)' 'f (const int) जैसा नहीं है)/एफ (int const *) ' – Roland

+0

शायद। लिंक: http://stackoverflow.com/questions/2121525/const-pointers-in-overload-resolution/2121616#2121616 – sehe

उत्तर

4

ठीक है, आप f(&x) कॉल के मामले में "अपेक्षित" फ़ंक्शन के कॉन्स्ट संस्करण को क्यों कॉल कर रहे हैं?

तर्क प्रकार int * है, जैसा कि आप पहले ही जानते हैं। तो f(int *) फ़ंक्शन का संस्करण f(const int *) संस्करण से बेहतर मिलान है, क्योंकि पूर्व में तर्क प्रकार बिल्कुल से मेल खाता है। कंपाइलर टेम्पलेट से f(int *) उत्पन्न करने का अवसर देखता है और यह वह अवसर लेता है। यह ठीक है कि यह सी ++ में कैसे काम करता है।

ऐसे मामलों में जब टेम्पलेट संस्करण गैर-टेम्पलेट के रूप में उतना ही अच्छा होता है, तो गैर-टेम्पलेट सामान्य रूप से जीतता है। लेकिन इस मामले में, जहां टेम्पलेट संस्करण स्पष्ट रूप से बेहतर है, टेम्पलेट संस्करण जीतता है।

स्पष्ट रूप से आप संकलक के फ़ंक्शन के गैर-टेम्पलेट संस्करण को चुनने की अपेक्षा करते हैं। क्यूं कर?

+0

मुझे उम्मीद थी कि यह एक मामूली और निहित कॉन्स रूपांतरण के कारण जीतने के लिए होगा। यह सिर्फ मुझे लगता है कि टेम्पलेट पर विचार करने से पहले एक सूचक प्रकार को अपग्रेड करना हमेशा होता है। शायद एक उदाहरण है कि यह एक अच्छा विचार क्यों नहीं होगा। – Roland

+4

@ रोलैंड: कोई रूपांतरण> ओवरलोड रिज़ॉल्यूशन में मामूली रूपांतरण। – ildjarn

+0

@ रोलैंड: कल्पना करें कि आपके पास ऑपरेशन करने के दो तरीके हैं। यह विनाशकारी है (इसके तर्क के संबंध में)। 'Const' संस्करण में, इसलिए आपको पहले तर्क की प्रतिलिपि करने की आवश्यकता है, जो स्पष्ट रूप से कम कुशल है। उदाहरण: 'टी एंड ऑपरेटर + (टी एंड एस, टी कॉन्स एंड)' टी ऑपरेटर + (टी कॉन्स एंड टी टी कॉन्स्ट एंड) 'से अधिक कुशल है। –

8

instantiated टेम्पलेट f<int *> कोई रूपांतरण के लिए (int * ->const int *) की जरूरत है, तो यह एक बेहतर मैच है - वास्तव में, यह एक सटीक मिलान है, कि केवल एक गैर टेम्प्लेटेड सटीक मिलान, जो क्या होता है के खिलाफ खो देगा दूसरी कॉल

"बेहतर मिलान" नियमों की पूर्ण व्याख्या सी ++ मानक के §13.3.3 पर उपलब्ध है।

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