Неявное преобразование из int в вектор?

vector<T> имеет конструктор, который принимает размер вектора, и, насколько я знаю, это явный, что может быть доказано тем фактом, что следующий код не компилируется

void f(std::vector<int> v);
int main()
{
f(5);
}

Я не могу понять и прошу вас объяснить, почему следующий код компилируется

std::vector<std::vector<int>> graph(5, 5);

Он не только компилируется, он фактически изменяет размер графика до 5 и устанавливает для каждого элемента вектор из пяти нулей, то есть делает то же самое, что и код, который я обычно пишу:

std::vector<std::vector<int>> graph(5, std::vector<int>(5));

Как? Зачем?

Компилятор: MSVC10.0


ОК, похоже, это ошибка MSVC (еще одна). Если кто-то может уточнить ошибку в ответе (то есть обобщить случаи, когда она воспроизводится), я бы с радостью принял ее

8

Решение

Это не совсем ошибка. Вопрос в том, что может пойти не так, чтобы разрешить второй кусок кода, пока первый не компилируется?

Проблема в том, что, хотя вам кажется очевидным, какой конструктор вы хотите вызвать, когда вы это делаете:

std::vector<std::vector<int>> graph(5, 5);

это не очень понятно для компилятора. В частности, есть две перегрузки конструктора, которые могут потенциально принимать аргументы:

vector(size_type,const T& value = T());

template <typename InputIterator>
vector(InputIterator first, InputIterator last);

Первый требует преобразования 5 в size_type (без знака), в то время как второй — идеальное совпадение, так что это будет тот, который подобрал компилятор …

… но компилятор требует, чтобы вторая перегрузка, если выведенный тип InputIterator Интеграл ведет себя так, как если бы это был вызов:

vector(static_cast<size_type>(first),static_cast<T>(last))

Что стандарт C ++ 03 эффективно предписывает, так это то, что второй аргумент эксплицитно конвертируется из оригинального типа int к типу назначения std::vector<int>, Поскольку преобразование явное, вы получаете ошибку.

Стандарт C ++ 11 изменяет формулировку, чтобы использовать SFINAE для отключения конструктора итератора, если аргумент на самом деле не является входным итератором, поэтому в компиляторе C ++ 11 код должен быть отклонен (что, вероятно, является причиной, по которой некоторые утверждают, что это быть ошибкой).

7

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

Мне кажется, это вызывает этот конструктор:

template <class InputIterator>
vector (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());

Я не уверен где explicit входит в это, потому что конструктор принимает несколько параметров. Это не автоматическое приведение от int к вектору.

2

На самом деле это расширение, а не ошибка.

Вызываемый конструктор — это тот, который принимает два итератора (но на самом деле сигнатура будет соответствовать любым двум параметрам одного типа); Затем он вызывает специализацию, когда два итератора на самом деле int, который явно создает value_type используя значение end и заполняет вектор begin копии этого.

1

станд :: вектор< int> имеет конструктор, который принимает size_type и const int&, Это тот конструктор, который я бы ожидал вызвать в этом случае, инициализируя вектор 5-ю целыми числами, каждое со значением 5.

-4
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector