为什么对重载函数的调用不明确?

时间:2020-03-01 21:40:44

标签: c++ templates iterator overloading initializer-list

考虑该程序-

#include <string>
#include <vector>
#include <set>
void fun(const std::string& val) {
}

void fun(std::vector<std::string> val) {
}

int main()
{
    std::set<std::string> example;
    fun({std::begin(example), std::end(example)});
}

在编译时,我遇到了这些错误-

prog.cc: In function 'int main()':
prog.cc:13:49: error: call of overloaded 'fun(<brace-enclosed initializer list>)' is ambiguous
   13 |     fun({std::begin(example), std::end(example)});
      |                                                 ^
prog.cc:4:6: note: candidate: 'void fun(const string&)'
    4 | void fun(const std::string& val) {
      |      ^~~
prog.cc:7:6: note: candidate: 'void fun(std::vector<std::__cxx11::basic_string<char> >)'
    7 | void fun(std::vector<std::string> val) {
      |      ^~~

我了解到std::string的构造函数重载像这样-{p}

initializer_list

basic_string( std::initializer_list<char> ilist, const Allocator& alloc = Allocator() ); 的重载看起来像这样-

std::vector<std::string>

因此,很明显,这两种方法的类型不同。一个使用vector( std::initializer_list<std::string> init, const Allocator& alloc = Allocator() ); 的{​​{1}},另一个使用initializer_list类型。

在我的代码中,当我传递字符串cos的初始化列表时,我将2个迭代器传递给一组字符串。

那么,为什么编译器仍将此标记为模棱两可的调用?

1 个答案:

答案 0 :(得分:5)

编译器看到对以下两个构造函数的模棱两可的调用(请注意,它们都不使用初始化列表):

template <class InputIt>
std::vector::vector (InputIt first, InputIt last, const Allocator& alloc = Allocator());

template <class InputIt>
std::string::string (InputIt first, InputIt last, const Allocator& alloc = Allocator());

现在,如果您实际上要使用那些迭代器参数来调用std::string构造函数,则会出现错误,因为它们没有取消引用char。但是由于该检查不是函数声明的一部分(例如通过SFINAE),所以您会得到歧义错误。