Объединение нескольких диапазонов без копирования
Я хочу объединить несколько диапазонов (эквекторов) в один диапазон, не копируя их в новый контейнер, чтобы повысить производительность.
Это для повторения всего диапазона позже.
#include <iostream>
#include <vector>
#include <boost/range/adaptors.hpp>
#include <boost/range.hpp>
const std::vector<int> vec1 = { 0, 1, 2, 3 };
const std::vector<int> vec2 = { 10, 11, 12, 13 };
const std::vector<int> vec3 = { 20, 21, 22, 23 };
const std::vector<int> vec4 = { 30, 31, 32, 33 };
std::vector< std::vector<int>> all{vec1, vec2, vec3, vec4};
int main() {
auto range = boost::adaptors::transform( all, [&](auto &v) {
return boost::make_iterator_range( v );
} );
for( const auto &i:range) {
std::cout << i << ", ";
}
}
Вышеприведенное печатает это;
0123, 10111213, 20212223, 30313233,
Но на самом деле я хочу вот этого;
0, 1, 2, 3, 10, 11, 12, 13, 20, 21, 22, 23, 30, 31, 32, 33,
3 ответа
Если вы можете использовать диапазоны С++20, а не повышать, вы можете сделать:
auto range = all | std::views::join
То же самое работает с библиотекой ranges-v3. Используя библиотеку ranges-v3, вы можете избежать создания
all
если это желательно:
auto range = ranges::views::concat(vec1, vec2, vec3, vec4);
С повышением вы можете сделать:
auto range =
boost::join(vec1,
boost::join(vec2,
boost::join(vec3, vec4)
)
);
На самом деле существует ranges::views::concat(), появившийся в C++23 2/3.
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2214r0.html
Один комментарий, прежде чем я дам свой ответ в старом стиле. Это то, что вы уже копируете все векторы при создании
all
в коде выше....
Потенциальное решение состоит в том, чтобы иметь вектор указателя на вектор.
std::vector< std::vector<int>*> all;
затем вы push_back адрес всех ваших векторов в вектор вектора. Только копирование адреса для каждого вектора оказывает меньшее влияние на производительность, чем копирование всего этого.
Затем вы сканируете вектор вектора, используя вложенный цикл.
for( auto temp:all)
for (int element:*temp)
{
std::cout << element << ", ";
}