编译器为什么前两次调用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;
}
答案 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"});
将调用您想要的函数。