2017-01-06 9 views
57

संकलक द्वारा doSomething पर पहले दो कॉल क्यों ठीक हैं, लेकिन सूची में दो तत्वों का उपयोग करके एक अस्पष्ट कॉल का कारण बनता है?प्रारंभकर्ता सूची में तत्वों की संख्या क्यों अस्पष्ट कॉल त्रुटि का कारण बनती है?

#include <vector> 
#include <string> 

void doSomething(const std::vector<std::string>& data) {} 

void doSomething(const std::vector<int>& data) {} 

int main(int argc, char *argv[]) 
{ 
    doSomething({"hello"}); // OK 
    doSomething({"hello", "stack", "overflow"}); // OK 
    doSomething({"hello", "stack"}); // C2668 'doSomething': ambiguous call 

    return 0; 
} 

उत्तर

56

यहां क्या हो रहा है यह है कि दो तत्व प्रारंभकर्ता सूची में दोनों स्ट्रिंग अक्षर दोनों को const char* में रूपांतरित कर दिया जा सकता है क्योंकि उनके प्रकार const char[N] हैं। अब std::vector में एक कन्स्ट्रक्टर है जो दो इटरेटर लेता है जो पॉइंटर्स क्वालीफाई करते हैं। std::vector<std::string> का कन्स्ट्रक्टर std::vector<int> के इटरेटर रेंज कन्स्ट्रक्टर के साथ विवादित है।

हम कोड को बदलते हैं बजाय

doSomething({"hello"s, "stack"s}); 

होने के लिए फिर प्रारंभकर्ता सूची के तत्वों अब कर रहे हैं std::string रों तो वहाँ कोई अस्पष्टता नहीं है।

+6

या 'कुछ करना (std :: vector ({"हैलो", "ढेर"});', लेकिन आपका समाधान अधिक पठनीय है। किसी भी मामले में, यदि यह वास्तविक कोड में है, तो शायद मैं प्रतीत होता है कि बेकार स्पष्टीकरण की व्याख्या करने के लिए मैं एक छोटी टिप्पणी भी जोड़ूंगा। –

+0

मैंने सोचा कि प्रारंभकर्ताइज़र_लिस्ट कन्स्ट्रक्टर को हमेशा संभव होने पर बुलाया जाता है, उदाहरण के लिए std :: vector {5,1} में तत्व 5 और 1 के साथ वेक्टर प्राप्त होता है और 5 गुना नहीं 1. यह मामला क्यों नहीं है? –

+0

@ ab.o2c प्रारंभकर्ता सूची निर्माता को प्राथमिकता दी जाती है लेकिन हमारे पास इस मामले में 'std :: vector {5,1} 'नहीं है। हमारे पास क्या है 'std :: vector {const char *, const char *} '। चूंकि प्रारंभकर्ता सूची में वेक्टर के तत्वों के समान प्रकार होना चाहिए, इसलिए इस मामले में इसे अनदेखा किया जाता है और इटरेटर कन्स्ट्रक्टर चुना जाता है। – NathanOliver

23

दोनों एक तर्क और तीन तर्क सूचियों केवल मिलान कर सकते हैं std::vector<std::string> के std::initializer_list निर्माता। हालांकि, दो तर्क सूची std::vector<int> से कंस्ट्रक्टर्स में से एक से मेल खाता है:

template <class InputIt> 
vector(InputIt first, InputIt last, Allocator const &alloc = Allocator()); 

वास्तव में, एक char const * वृद्धि की जा सकती है, और एक char कि परोक्ष एक int के लिए परिवर्तनीय है पाने के लिए dereferenced।

16

"hello" और "stack"const char * करने के लिए दोनों क्षय जो InputIterator अवधारणा संतुष्ट करता है। यह उन्हें std::vector's constructor #4 से मिलान करने की अनुमति देता है।

यदि आप std::string ऑब्जेक्ट पास करते हैं तो अस्पष्टता हल हो जाती है।

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