Wiebe Wiebe - 2 months ago 11
C++ Question

Resize recursive nested vector in template

I'm trying to make a template function that resizes a nested vector in all it's dimensions.

Pretty much like this: resizing multidimensional vector , but for an arbitrary nr. of dims.

(I suppose) The function would (at least) accept a reference to the vector (or vector> or v>>, etc.) and a vector with the desired sizes. I now also have in index in the sizes vector, but it's probably not needed.

So far, this is what I ended up with (could be completely wrong):

template<typename V> void resize(vector<V> & V1, vector<int32_t> t, int32_t index) {
int32_t current_size=t.at(index);
cout << "resize dim [" << index << "] to size " << current_size <<endl ;
++index;
if (index < t.size()) {
// for each element ??
// for( int i = 0 ; i < V1.size(); i++ ) { resize (V1.at(i), t, index); } // doesn't work
// for( auto const& e : V1 ) { resize (e, t, index); } // doesn't work
// resize( V1, t, index); // recursive call, works, but doesn't do anything
}


I'd like to avoid copies of V1 or any of it's content. I'm not sure if there is a way with an iterator or for loop that passes references. If not, there probably needs to be a forth input to keep the index of V1?

Btw., I'm skipping the first dim on purpose, it is already the correct size.

Any help appreciated.

Answer

You're probably looking for something like this (this is c++14-compliant solution, similar one would be a little bit more tricky for c++11 but still possible):

#include <vector>
#include <tuple>
#include <utility>

template <class NestedVectorElement, class Tuple>
void nested_resize(std::vector<std::vector<NestedVectorElement>> &v, Tuple &&t);

template <class VectorElement, class Tuple>
void nested_resize(std::vector<VectorElement> &v, Tuple &&t);

template <class Vector, class Tuple, size_t... Is>
void nested_resize_impl(Vector &v, Tuple &&t, std::index_sequence<Is...>) {
   v.resize(std::get<0>(t));
   for(auto &nv: v) {
      nested_resize(nv, std::forward_as_tuple(std::get<Is + 1>(t)...));
   }
}

template <class NestedVectorElement, class Tuple>
void nested_resize(std::vector<std::vector<NestedVectorElement>> &v, Tuple &&t) {
   nested_resize_impl(v, t, std::make_index_sequence<std::tuple_size<Tuple>::value - 1>{});
}

template <class VectorElement, class Tuple>
void nested_resize(std::vector<VectorElement> &v, Tuple &&t) {
   v.resize(std::get<0>(t));
}

int main() {
   std::vector<std::vector<std::vector<int>>> matrix;
   nested_resize(matrix, std::make_tuple(3, 2, 3));
   matrix.at(2).at(1).at(2) = 0; // at gives you an access only if element exists else throws an exception
}