Подтвердить что ты не робот

Почему количество элементов в списке инициализаторов вызывает неоднозначную ошибку вызова?

Почему первые два вызова doSomething OK компилятором, но использование двух элементов в списке вызывает неоднозначный вызов?

#include <vector>
#include <string>

void doSomething(const std::vector<std::string>& data) {}

void doSomething(const std::vector<int>& data) {}

int main(int argc, char *argv[])
{
    doSomething({"hello"}); // OK
    doSomething({"hello", "stack", "overflow"}); // OK
    doSomething({"hello", "stack"}); // C2668 'doSomething': ambiguous call

    return 0;
}
4b9b3361

Ответ 1

Что здесь происходит, так это то, что в списке инициализаторов элементов оба строковых литерала могут быть неявно преобразованы в const char*, так как их тип const char[N]. Теперь std::vector имеет конструктор, который принимает два итератора, к которым подходят указатели. Из-за этого конструктор initializer_list std::vector<std::string> противоречит конструктору диапазона итератора std::vector<int>.

Если мы изменим код, вместо него будем

doSomething({"hello"s, "stack"s});

Затем элементы списка инициализаторов теперь std::string, поэтому нет двусмысленности.

Ответ 2

Оба списка с одним аргументом и тремя аргументами могут соответствовать только конструктору std::vector<std::string> std::initializer_list. Однако список с двумя аргументами соответствует одному из конструкторов из std::vector<int>:

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

Действительно, a char const * можно увеличить и разыменовать, чтобы получить char, который неявно конвертируется в int.

Ответ 3

"hello" и "stack" оба распадаются на const char *, что удовлетворяет концепции InputIterator. Это позволяет им сопоставлять конструктор std::vector конструктор # 4.

Если вы передаете объекты std::string, неоднозначность будет разрешена.