我真的不明白这一点,我以为编译器会先执行大括号中的内容,然后将结果传递给最合适的函数。这里它看起来像是给了函数一个初始化列表来处理它…
#include <string>
#include <vector>
using namespace std;
void func(vector<string> v) { }
void func(vector<wstring> v) { }
int main() {
func({"apple", "banana"});
}
错误:
<stdin>: In function 'int main()':
<stdin>:11:27: error: call of overloaded 'func(<brace-enclosed initializer list>)' is ambiguous
<stdin>:11:27: note: candidates are:
<stdin>:6:6: note: void func(std::vector<std::basic_string<char> >)
<stdin>:8:6: note: void func(std::vector<std::basic_string<wchar_t> >)
为什么没有调用我的 func(vector<string> v)
重载,我可以这样做吗?
发布于 2013-01-30 01:34:09
这是一个微妙的问题。
std::vector
有一个接受两个范围迭代器的构造函数。它是一个模板构造函数(在C++11标准的23.6.6.2中定义):
template<typename InputIterator>
vector(InputIterator first, InputIterator last,
const allocator_type& a = allocator_type());
现在,std::vector<wstring>
接受initializer_list
的构造器与函数调用中的隐式转换不匹配(const char*
和string
是不同的类型);但是上面的构造器(当然包含在std::vector<string>
和std::vector<wstring>
中)可能是一个完美的匹配项,因为InputIterator
可以推断为const char*
。除非使用一些SFINAE技术来检查推导出的模板参数是否确实满足向量底层类型的InputIterator
概念(这不是我们的情况),否则这个构造函数是可行的。
但话又说回来,std::vector<string>
和std::vector<wstring>
都有一个可行的构造函数,可以实现从带括号的初始化器列表的转换:因此,有歧义。
所以问题在于,尽管"apple"
和"banana"
不是真正的迭代器(*),但它们最终被视为迭代器。将一个参数"joe"
添加到函数调用可以通过消除调用的歧义来解决这个问题,因为这会迫使编译器排除基于范围的构造函数,并选择仅可行转换(initializer_list<wstring>
不可行,因为const char*
不能转换为wstring
)。
*实际上,它们是指向const char
的指针,因此它们甚至可以被视为字符的常量迭代器,但绝对不是我们的模板构造函数愿意考虑的字符串的迭代器。
https://stackoverflow.com/questions/14587436
复制相似问题