Почему этот вызов перегруженной функции неоднозначен? - PullRequest
1 голос
/ 02 марта 2020

Рассмотрим эту программу -

#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 имеет перегрузку конструктора, которая принимает initializer_list вроде so-

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() );

Итак, ясно, что эти 2 метода различаются по своим типам. Один принимает initializer_list из char, а другой типа std::string.

В моем коде, когда я передаю список строк инициализатора, потому что я передаю 2 итератора в набор строк.

Даже тогда, почему компилятор помечает это как неоднозначный вызов?

1 Ответ

5 голосов
/ 02 марта 2020

Компилятор видит неоднозначный вызов следующих двух конструкторов (обратите внимание, что ни один из них не берет список инициализатора):

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 с этими аргументами итератора, вы получите ошибку, потому что они не обращаются к символу. Но поскольку эта проверка не является частью объявления функции (например, через SFINAE), вместо этого вы получаете ошибку неоднозначности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...