问题
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;
}
回答1:
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.
回答2:
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.
回答3:
"hello" and "stack" both decay to const char * which satisfies the InputIterator concept. This allow's them to match std::vector's constructor #4.
If you pass std::string objects the ambiguity is resolved.
来源:https://stackoverflow.com/questions/41507602/why-does-the-number-of-elements-in-a-initializer-list-cause-an-ambiguous-call-er