2012-01-07 19 views
31

जबएक पूर्णांक अक्षर के साथ ओवरलोडेड एंबिग (लम्बा) और अंबिग (हस्ताक्षरित लंबा) कॉल करने के लिए यह संदिग्ध क्यों है?

void ambig( signed long) { } 
void ambig(unsigned long) { } 

int main(void) { ambig(-1); return 0; } 

संकलन मैं

error C2668: 'ambig' : ambiguous call to overloaded function 
    could be 'void ambig(unsigned long)' 
    or 'void ambig(long)' 
while trying to match the argument list '(int)' 

मैं जानता हूँ कि मैं 'ठीक' यह कर सकते हैं -1 के बजाय -1L कह कर मिलता है, लेकिन क्यों/कैसे वास्तव में इस पहली जगह में अस्पष्ट माना जाता है?

उत्तर

33

आप इस अधिभारित फ़ंक्शन पर int पास कर रहे हैं।

हालांकि मानव अंतर्ज्ञान का कहना है कि ambig(signed long) पसंद किया जा सकता है क्योंकि आपके इनपुट के एक नकारात्मक पूर्णांक (जो एक unsigned long द्वारा इस तरह के रूप में प्रतिनिधित्व नहीं किया जा सकता) है चाहिए, दो रूपांतरण "पूर्वता" C++ में तथ्य बराबर में हैं।

है, रूपांतरण intunsigned long बस के रूप में मान्य int रूप → signed long माना जाता है, और न तो दूसरे के लिए पसंद किया जाता है।

दूसरी ओर, यदि आपके पैरामीटर पहले से ही एक long बजाय एक int थे, तो वहाँ एक सटीक मिलान signed long करने के लिए, कोई रूपांतरण आवश्यक के साथ है। This avoids the ambiguity

void ambig( signed long) { } 
void ambig(unsigned long) { } 

int main(void) { ambig(static_cast<long>(-1)); return 0; } 

"बस उन चीजों में से एक"।


[C++11: 4.13/1]: ("पूर्णांक रूपांतरण रैंक")

हर पूर्णांक प्रकार एक पूर्णांक रूपांतरण रैंक के रूप में परिभाषित किया गया है इस प्रकार है:

  • [..]
  • के पद एक हस्ताक्षरित पूर्णांक प्रकार किसी छोटे आकार के साथ किसी भी हस्ताक्षरित पूर्णांक प्रकार के रैंक से अधिक होगा।
  • long long int के पद long int, जो int के पद है, जो short int के पद से भी बड़ा होगा की तुलना में अधिक हो जाएगा के पद से भी बड़ा होगा, जो हस्ताक्षर किए के पद से अधिक होना होगा चार।
  • किसी भी हस्ताक्षरित पूर्णांक प्रकार का रैंक संबंधित हस्ताक्षरित पूर्णांक प्रकार के रैंक के बराबर होगा।
  • [..]

[नोट: पूर्णांक रूपांतरण रैंक अभिन्न प्रोन्नति (4 की परिभाषा में प्रयोग किया जाता है।5) और सामान्य अंकगणितीय रूपांतरण (खंड 5)। अंत टिप्पणी]

अधिभार संकल्प जटिल है, और [C++11: 13.3] में परिभाषित किया गया है; मैं यहां बहुमत उद्धृत करके आपको नहीं बोलेगा।

यहाँ, एक मुख्य आकर्षण है, हालांकि:

[C++11: 13.3.3.1/8]: बिना किसी रूपांतरण एक पैरामीटर प्रकार के लिए एक तर्क के मैच के लिए आवश्यक है, तो अंतर्निहित रूपांतरण अनुक्रम मानक रूपांतरण पहचान रूपांतरण (13.3.3.1 से मिलकर अनुक्रम है। 1)।

[C++11: 13.3.3.1/9]: यदि किसी पैरामीटर प्रकार में तर्क को परिवर्तित करने के लिए रूपांतरणों का कोई अनुक्रम नहीं पाया जा सकता है या रूपांतरण अन्यथा खराब हो गया है, तो एक अंतर्निहित रूपांतरण अनुक्रम नहीं बनाया जा सकता है।

[C++11: 13.3.3.1/10]: यदि रूपांतरण के कई अलग-अलग अनुक्रम मौजूद हैं कि प्रत्येक तर्क को पैरामीटर प्रकार में परिवर्तित करता है, पैरामीटर से जुड़े अंतर्निहित रूपांतरण अनुक्रम को अद्वितीय रूपांतरण अनुक्रम माना जाता है जो संदिग्ध रूपांतरण अनुक्रम को निर्दिष्ट करता है। 13.3.3.2 में वर्णित निहित रूपांतरण अनुक्रमों के रैंकिंग के उद्देश्य के लिए, संदिग्ध रूपांतरण अनुक्रम को उपयोगकर्ता द्वारा परिभाषित अनुक्रम के रूप में माना जाता है जो किसी अन्य उपयोगकर्ता द्वारा परिभाषित रूपांतरण अनुक्रम 134 से अलग नहीं है। यदि संदिग्ध रूपांतरण अनुक्रम का उपयोग करने वाला कोई फ़ंक्शन सबसे व्यवहार्य कार्य के रूप में चुना जाता है, तो कॉल खराब हो जाएगा क्योंकि कॉल में तर्कों में से एक का रूपांतरण संदिग्ध है।

  • /10 मामले आप अनुभव कर रहे है, /8 वह मामला है जिसका उपयोग आप long तर्क के साथ करते हैं।
+2

प्रतीक्षा करें, लेकिन 'int' → 'long' हमेशा एक लापरवाही रूपांतरण है। 'int' → 'हस्ताक्षरित लंबा' समय आधा समय है। वे एक ही रैंक कैसे/क्यों हैं ?! – Mehrdad

+10

बस जिज्ञासा: किसी भी कारण से उस कास्ट के बजाय '-1L' का उपयोग न करें? – Mat

+0

@Mat: नहीं, कोई नहीं। –

3

क्योंकि -1int प्रकार का है। और int को या तो signed long या unsigned long पर परिवर्तित किया जा सकता है।

8

निरंतर -1 प्रकार int है। तो आप ambig को int पर तर्क के रूप में कॉल कर रहे हैं। ambig में एक अधिभार नहीं है जो int स्वीकार करता है, इसलिए हमें उन अनुमानित रूपांतरणों को देखना होगा जिन्हें हम कर सकते हैं। int को long या unsigned long (अन्य चीजों के साथ) में रूपांतरित किया जा सकता है, जिनमें से दोनों ambig पर मान्य तर्क होंगे। इसलिए संकलक को यह नहीं पता कि कौन से रूपांतरण को चुनना है और आपको मैन्युअल रूप से डालने की आवश्यकता है (या शुरू करने के लिए एक निरंतर स्थिरता के बजाय एक लंबे स्थिर (-1l) का उपयोग करें)।

तथ्य यह है कि -1 एक ऋणात्मक संख्या इसमें कारक नहीं है क्योंकि संकलक तर्क प्रकार को नहीं देखता है, बस इसके प्रकार।

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