2017-06-29 18 views
6

किसी भी भ्रम को रोकने के लिए, सरणी और पॉइंटर्स, क्षय-से-पॉइंटर की अवधारणा और द्वारा सरणी को पार करने की अवधारणा के बीच अंतर को बहुत समझता है। सी ++ में संदर्भ, आदिफंक्शन तर्क बाईंडिंग नियम संदर्भ बनाम पॉइंटर

मेरा प्रश्न यहाँ विशेष रूप से समारोह अधिभार उम्मीदवारों का एक सेट है, जब एक अधिभार एक सरणी संदर्भ लेता से एक समारोह का चयन करने के संकलक द्वारा इस्तेमाल किया नियमों के बारे में, और अन्य है अधिभार एक सूचक लेता है।

उदाहरण के लिए, मान लीजिए हमने:

template <class T, std::size_t N> 
void foo(const T (&arr)[N]) 
{ 
    std::cout << "Array-reference overload!" << std::endl; 
} 

template <class T> 
void foo(const T* ptr) 
{ 
    std::cout << "Pointer overload!" << std::endl; 
} 

हम इस प्रकार समारोह टेम्पलेट foo() आह्वान करने के लिए प्रयास करते हैं:

const char arr[2] = "A"; 
foo(arr); 

... तो मेरी उम्मीद होगी कि पहले अधिभार, जो एक सरणी संदर्भ लेता है, संकलक द्वारा चुना जाएगा।

हालांकि, जीसीसी 4.9.2 का उपयोग कर, अगर मैं इसके बाद के संस्करण कोड संकलन, मैं कोई त्रुटि मिलती है:

test.cpp:28:9: error: call of overloaded ‘foo(const char [2])’ is ambiguous 

यह क्यों दोनों भार के यहाँ संकलक द्वारा समान रूप से अच्छे उम्मीदवारों माना जाता है मेरे लिए स्पष्ट नहीं है, के बाद से पहला अधिभार ठीक प्रकार से मेल खाता है, जबकि दूसरे ओवरलोड को अतिरिक्त क्षय-से-पॉइंटर चरण की आवश्यकता होती है।

अब, मैं ऊपर स्पष्ट रूप से type_traits का उपयोग कर के रूप में निम्नानुसार द्वारा काम कर अधिभार प्राप्त करने में सक्षम हूँ:

template <class T, std::size_t N> 
void foo(const T (&arr)[N]) 
{ 
    std::cout << "Array-reference overload!" << std::endl; 
} 

template <class T> 
void foo(T ptr, typename std::enable_if<std::is_pointer<T>::value>::type* = 0) 
{ 
    std::cout << "Pointer overload!" << std::endl; 
} 

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

उत्तर

4

the first overload matches the type exactly, whereas the second overload requires an extra decay-to-pointer step.

क्योंकि जब overload resolution में ranking of implicit conversion sequences जाँच, array-to-pointer conversion एक सटीक मिलान के रूप में माना जाता है, इस प्रकार 2 अधिभार 1 एक के साथ एक ही रैंक है।

मानक से, $16.3.3.1.1 Standard conversion sequences [over.ics.scs] Table 13 — Conversions

Conversion     Category    Rank   Subclause 
No conversions required  Identity    Exact Match 
... ... 
Array-to-pointer conversion Lvalue Transformation Exact Match [conv.array] 
... ... 

यह ध्यान देने योग्य है कि "कोई रूपांतरण के लिए आवश्यक" (यानी 1 अधिभार के लिए मामला) रैंक है "सटीक मिलान" बहुत लायक है।

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