Этот был тонким.
std::vector
имеет конструктор, принимающий два итератора диапазона. Это конструктор template (определенный в 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>
не< /em> жизнеспособно, потому что const char*
нельзя преобразовать в wstring
).
*На самом деле они являются указателями на const char
, поэтому их можно даже рассматривать как константные итераторы для символов, но определенно не для строк, как хочет думать наш конструктор шаблонов.
person
Andy Prowl
schedule
29.01.2013