为什么初始化列表中的元素数量会导致模棱两可的调用错误?

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

为什么编译器对 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;
}

单参数和三参数列表都只能匹配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

这里发生的是,在双元素初始值设定项列表中,两个字符串文字都可以隐式转换为 const char*,因为它们的类型是 const char[N]。现在 std::vector 有一个构造函数,它接受两个指针符合条件的迭代器。因此 std::vector<std::string>initializer_list 构造函数与 std::vector<int>.

的迭代器范围构造函数冲突

如果我们将代码更改为

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

然后初始化列表的元素现在是 std::strings 所以没有歧义。

"hello""stack" 都衰减到 const char * 满足 InputIterator concept. This allow's them to match std::vector's constructor #4.

如果你传递 std::string 个对象,歧义就解决了。

也许您可以使用 initializer_list 参数重载 doSomething(),如下所示:

void doSomething(initializer_list<string> l) {
    doSomething(vector<string>(l));
}

然后,doSomething({"hello", "stack"}); 将调用您想要的函数。