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

时间:2017-01-06 14:15:45

标签: c++ initializer-list ambiguous overload-resolution

编译器为什么前两次调用doSomething OK,但是使用列表中的两个元素会导致调用不明确?

#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;
}

4 个答案:

答案 0 :(得分:58)

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

如果我们将代码更改为

std::vector<int>

然后初始化列表的元素现在是doSomething({"hello"s, "stack"s}); s,所以没有歧义。

答案 1 :(得分:23)

单参数列表和三参数列表都只能匹配std::vector<std::string>的{​​{1}}构造函数。但是,双参数列表与std::initializer_list

中的一个构造函数匹配
std::vector<int>

确实,template <class InputIt> vector(InputIt first, InputIt last, Allocator const &alloc = Allocator()); 可以递增,并取消引用以获得可隐式转换为char const *的{​​{1}}。

答案 2 :(得分:16)

()?"hello"都会衰减到满足InputIterator概念的"stack"。这允许他们匹配std::vector's constructor #4

如果您传递const char *个对象,则歧义将得到解决。

答案 3 :(得分:0)

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

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

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