вызов перегруженного & lt; заключенного в скобки списка инициализатора & gt; неоднозначно, как с этим бороться?

Я действительно не понимаю этого, я думал, что компилятор сначала выполняет то, что в скобках, а затем дает результат наиболее подходящей функции. Здесь похоже, что она дает функции список инициализатора, чтобы справиться с ней …

#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) вызвана перегрузка, и можно ли так сделать?

19

Решение

Этот был тонким.

std::vector имеет конструктор, принимающий два итератора диапазона. Это шаблон конструктор (определенный в 23.6.6.2 Стандарта C ++ 11):

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так что они могут даже рассматриваться как постоянные итераторы для персонажи, но определенно не для строк, как думает наш конструктор шаблонов.

24

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]