По сути, та же идея, за исключением того, что она компилируется и немного более итеративна:
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
template <typename I, typename O>
void copyRectFromBiggerRect(
I input,
O output,
std::size_t startx,
std::size_t cols,
std::size_t starty,
std::size_t rows,
std::size_t stride
) {
std::advance(input, starty*stride + startx);
while(rows--) {
std::copy(input, input+cols, output);
std::advance(input, stride);
}
}
template<typename T>
std::vector<T> copyRectFromVector (
const std::vector<T> &vec,
std::size_t startx,
std::size_t starty,
std::size_t endx,
std::size_t endy,
std::size_t stride
) {
// parameter-checking omitted: you could also check endx > startx etc.
const std::size_t cols = endx - startx;
const std::size_t rows = endy - starty;
std::vector<T> ret;
ret.reserve(rows*cols);
std::back_insert_iterator<std::vector<T> > output(ret);
typename std::vector<T>::const_iterator input = vec.begin();
copyRectFromBiggerRect(input,output,startx,cols,starty,rows,stride);
return ret;
}
int main() {
std::vector<int> v(20);
for (int i = 0; i < 20; ++i) v[i] = i;
std::vector<int> v2 = copyRectFromVector(v, 0, 0, 1, 2, 4);
std::copy(v2.begin(), v2.end(), std::ostream_iterator<int>(std::cout, "\n"));
}
Я бы не ожидал, что это будет быстрее, чем копирование двух циклов по индексу. Возможно, даже медленнее, хотя в основном это гонка между издержками vector :: push_back и усилением std :: copy по циклу.
Однако это может быть более гибким, если ваш другой код шаблона предназначен для работы с итераторами в целом, а не с вектором в качестве отдельного контейнера. copyRectFromBiggerRect может использовать массив, деку или даже список в качестве входных данных так же легко, как вектор, хотя в настоящее время он не оптимален для итераторов, которые не имеют произвольного доступа, поскольку в настоящее время он перемещается по каждой скопированной строке дважды.
Для других способов сделать это более похожим на другой код C ++, рассмотрите boost :: multi_array для многомерных массивов (в этом случае реализация в любом случае будет полностью отличаться от этого), и избегайте возврата коллекций, таких как vector by value ( во-первых, это может быть неэффективно, если вы не получите оптимизацию возвращаемого значения, и, во-вторых, так, чтобы контроль над тем, какие ресурсы были выделены, оставался на максимально возможном уровне).