Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the number of elements in a initializer list cause an ambiguous call error?

Why are the first two calls to doSomething OK by the compiler, but using two elements in the list causes an ambiguous call?

#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; } 
like image 291
koolbanana Avatar asked Jan 06 '17 14:01

koolbanana


Video Answer


2 Answers

What is happening here is that in the two element initializer list both of the string literals can be implicitly converted to const char* since their type is const char[N]. Now std::vector has a constructor that takes two iterators which the pointers qualify for. Because of that the initializer_list constructor of the std::vector<std::string> is conflicting with the iterator range constructor of std::vector<int>.

If we change the code to instead be

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

Then the elements of the initializer list are now std::strings so there is no ambiguity.

like image 132
NathanOliver Avatar answered Sep 27 '22 22:09

NathanOliver


Both the one-argument and three-argument lists can only match std::vector<std::string>'s std::initializer_list constructor. However, the two-argument list matches one of the constructors from std::vector<int>:

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

Indeed, a char const * can be incremented, and dereferenced to get a char that is implicitly convertible to an int.

like image 32
Quentin Avatar answered Sep 27 '22 21:09

Quentin