为什么初始化列表中的元素数量会导致模棱两可的调用错误?
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::string
s 所以没有歧义。
"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"});
将调用您想要的函数。
为什么编译器对 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::string
s 所以没有歧义。
"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"});
将调用您想要的函数。