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

Pav*_*ath 1 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)});
}
Run Code Online (Sandbox Code Playgroud)

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

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) {
      |      ^~~
Run Code Online (Sandbox Code Playgroud)

我知道它std::string有一个构造函数重载,它接受initializer_list类似这样的 -

basic_string( std::initializer_list<char> ilist,
              const Allocator& alloc = Allocator() );
Run Code Online (Sandbox Code Playgroud)

并且std::vector<std::string>有一个看起来像这样的过载-

vector( std::initializer_list<std::string> init,
        const Allocator& alloc = Allocator() );
Run Code Online (Sandbox Code Playgroud)

因此,很明显这两种方法的类型不同。一个接受initializer_listof char,另一个接受 type std::string

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

即便如此,为什么编译器会将此标记为不明确的调用?

Dar*_*uuk 5

The compiler sees an ambiguous call to the following two constructors (note that neither of them take an initializer list):

template <class InputIt>
std::vector::vector (InputIt first, InputIt last, const Allocator& alloc = Allocator());
Run Code Online (Sandbox Code Playgroud)

and

template <class InputIt>
std::string::string (InputIt first, InputIt last, const Allocator& alloc = Allocator());
Run Code Online (Sandbox Code Playgroud)

Now, if you were to actually call the std::string constructor with those iterator arguments you'd get an error, because they don't dereference to a char. But since that check is not part of the function declaration (e.g. via SFINAE), you're getting the ambiguity error instead.

  • @PavanManjunath那是因为它是一个文字“初始化列表”来初始化某些东西(可能是也可能不是`std::initializer_list`,例如,这里它是一个向量或字符串),它还没有被解析为还没有类型,所以这就是编译器能说的。像 `std::vector&lt;std::string&gt;{5, "abc"}` 不会调用 `std::initializer_list` 构造函数,但它仍然使用大括号括起来的 init-list 进行初始化(使用 2论据)。 (3认同)