Home > Net >  Dynamically allocate ragged matrix
Dynamically allocate ragged matrix

Time:05-04

I'm trying to make a generic function which will dynamically allocate 2D structure. Number of elements in every row doesn't have to be same for all rows. Structure is represented as a container type, whose elements are again of a container type (for example a set of lists). The type of elements of that inner container can also be arbitrary. Containers only support the begin, end, and size functions. Iterator operations must be supported for all iterator types. The function should first dynamically allocate the space for storing the 2D structure by the continuous allocation procedure, and then rewrite the elements of the structure it has accepted into the dynamic structure. The function returns a double pointer through which the elements of this structure can be accessed.

#include <iostream>
#include <set>
#include <list>
#include <vector>
template < typename tip >
  auto Make2DStructure(tip mat) {
    using tip_objekta = typename std::decay < decltype(mat[0][0]) > ::type;
    tip_objekta ** dynamic_mat = nullptr;
    int rows = 0, total = 0;
    for (auto i: mat) {
      rows  ;
      for (auto j: i)
        total  ;
    }
    int columns[rows];
    int k = 0;
    for (auto i: mat) {
      int num_of_colums = 0;
      for (auto j: i)
        num_of_colums  ;
      columns[k] = num_of_colums;
      k  ;
    }

    try {
      dynamic_mat = new tip_objekta * [rows];
      dynamic_mat[0] = new tip_objekta[total];
      for (int i = 1; i < rows; i  )
        dynamic_mat[i] = dynamic_mat[i - 1]   columns[i];
      for (int i = 0; i < rows; i  )
        for (int j = 0; j < columns[i]; j  )
          dynamic_mat[i][j] = mat[i][j];
    } catch (...) {
      delete[] dynamic_mat[0];
      delete[] dynamic_mat;
      throw std::bad_alloc();
    }
    return dynamic_mat;
  }

int main() {
    std::vector<std::vector<int>>mat{
        {1,2},
        {3,4,5,6},
        {7,8,9}
    };
    int columns[3]={2,4,3};
  try {
    int ** dynamic_mat = Make2DStructure(mat);
    for (int i = 0; i < 3; i  ) {
      for (int j = 0; j < columns[i]; j  )
        std::cout << dynamic_mat[i][j] << " ";
      std::cout << std::endl;
    }
    delete[] dynamic_mat[0];
    delete[] dynamic_mat;
  } catch (...) {
    std::cout << "Problems with memory";
  }
  return 0;
}

How could I modify this to work without indexing inside Make2DStrucure()?

Also, if I used std::set<std::list<int>> instead of std::vector<std::vector<int>> in main function I would have deduction problems. How could I modify this to work for different outside and inside container?

CodePudding user response:

Here's one way to accomplish what you want:

#include <iterator>
#include <type_traits>

template <typename tip>
auto Make2DStructure(tip mat) {
    // create an alias for the value type:
    using value_type = std::remove_cv_t<std::remove_reference_t<
        decltype(*std::begin(*std::begin(std::declval<tip>())))>>;

    // allocate memory for the return value, the pointer-pointer:    
    value_type** rv = new value_type*[mat.size()];

    // Calculate the number of values we need to allocate space for:
    size_t values = 0;
    for(auto& inner: mat) values  = inner.size();
    
    // allocate the space for the values:
    value_type* data = new value_type[values];

    // loop over the outer and inner container and keep the index running:   
    size_t idx = 0;

    for(auto& inner : mat) {
        // assign the outer pointer into the flat data block:
        rv[idx  ] = data;
        for(auto& val : inner) {
            // assign values in the data block:
            *data   = val;
        }
    }

    return rv;
}
  • Related