Предположим, у меня есть std::vector
размера, известного во время компиляции, и я хочу превратить его в std::array
. Как мне это сделать? Есть ли стандартная функция для этого?Использовать std :: vector для std :: array initialization
Лучшее решение, которое я до сих пор это:
template<class T, std::size_t N, class Indexable, std::size_t... Indices>
std::array<T, N> to_array_1(const Indexable& indexable, std::index_sequence<Indices...>) {
return {{ indexable[Indices]... }};
}
template<class T, std::size_t N, class Indexable>
std::array<T, N> to_array(const Indexable& indexable) {
return to_array_1<T, N>(indexable, std::make_index_sequence<N>());
}
std::array<Foo, 123> initFoos {
std::vector<Foo> lst;
for (unsigned i = 0; i < 123; ++i)
lst.push_back(getNextFoo(lst));
return to_array<Foo, 123>(lst); // passing lst.begin() works, too
}
Применение аналогично Populate std::array with non-default-constructible type (no variadic templates): У меня тоже есть тип, который не по-умолчанию, конструктивны, так что мне нужно, чтобы вычислить фактические значения К время, когда массив инициализируется. Однако, вопреки этому вопросу, для меня значения являются не просто функцией индекса, но и предыдущих значений. Я могу строить свои ценности гораздо проще с помощью цикла, чем с помощью ряда вызовов функций. Поэтому я строю элементы в цикле и помещаю их в вектор, тогда я хочу использовать конечное состояние этого вектора для инициализации массива.
Выше, кажется, компилируется и работает нормально, но, возможно, есть способы его улучшить.
- Возможно, я мог бы умело использовать некоторые стандартные функции библиотеки, о которых я не знал.
- Возможно, я могу как-то избежать вспомогательной функции.
- Возможно, я могу как-то сформулировать это так, чтобы он работал с семантикой перемещения для элементов вместо семантики копирования, используемой выше.
- Возможно, я могу избежать случайного доступа, используя
operator[]
, и вместо этого использовать семантику прямого итератора только для того, чтобы она работала дляstd::set
илиstd::forward_list
в качестве ввода. - Возможно, мне следует прекратить использовать
std::vector
и вместо этого выразить свою цель, используя вместо этогоstd::array<std::optional<T>, N>
, используя C++ 17 или некоторую эквивалентную реализацию.
Похожие вопросы:
- Copy std::vector into std::array который не принимает тип без конструктора по умолчанию, поэтому копирование после инициализации по умолчанию, это возможно там, но не для меня.
- Populate std::array with non-default-constructible type (no variadic templates), который вычисляет каждый элемент из своего индекса независимо, поэтому он пытается избежать промежуточного контейнера. Ответы используют вариативные шаблоны, даже если заголовок требует их избегать.
Интересная проблема, но это плохо пахнет. Зачем нужно генерировать данные только для их копирования? Это заставляет ваше желание упаковать их в 'std :: array', но в чем преимущество этого по сравнению с исходным' std :: vector'? Оба сохраняют данные в последовательной части памяти, поэтому не должно быть преимуществ первого по сравнению с последним. Единственное различие заключается в том, что 'size' является переменной времени компиляции, но это так или иначе. – Walter
@Walter: Действительный вопрос. С одной стороны, мой оригинал является «std :: set», поэтому мне нужно преобразовать хотя бы один раз. И я использую конструктор преобразования для выполнения преобразования типов для элементов. Таким образом, дело не только в том, чтобы хранить 'std :: vector'. Я мог бы использовать его. Главным аргументом против, наверное, является мое чувство, что чем больше компилятор знает, тем лучше он может оптимизировать. На практике я имею дело только с 24 элементами, и хотя это может быть слишком много для полной развертки цикла, это может быть, например, разворачивают группы из четырех человек, зная, что счет делится на 4. Просто чувство. – MvG