Reputation: 2612
I am trying to make a generic matrix struct in C++ but right now all I've got is
struct matrix{
int cells[dim][dim];
}
where dim is a const int.
However I wish to make things a little more dynamic so I can declare matrices of different sizes. I can get around this issue by converting everything to vectors of int vectors, but then I suffer a massive speed loss.
Upvotes: 2
Views: 199
Reputation: 43
You can also use a single vector for matrix class which works pretty well since the data will be sequential depending on row or column based storage. For example
Struct Matrix {
std::vector<int> cells;
int nrows, ncols;
Matrix(int rows, int cols) : cells(rows * cols), nrows(rows), ncols(cols)
{}
int& operator()(int row, int col){
return cells[row * ncols + col];
}
void resize(int rows, int cols){
cells.resize(rows*cols);
nrows = rows;
ncols = cols;
}
}
This is a nice vector wrapper for a matrix that avoids you needing to use c-style things.
Upvotes: 2
Reputation: 393084
FWIW I'd always go with a flat vector (pre-reserved/sized) or Boost MultiArray.
However, what's wrong with a template?
template<typename T, size_t N, size_t M=N>
struct matrix {
typedef T row_type[M];
row_type cells[N];
row_type* begin() { return std::begin(cells); }
row_type* end() { return std::end(cells); }
row_type const* begin() const { return std::begin(cells); }
row_type const* end() const { return std::end(cells); }
};
Or even better, with std::array
:
#include <array>
template<typename T, size_t N, size_t M=N>
struct matrix {
typedef std::array<T, M> row_type;
std::array<row_type, N> cells;
row_type* begin() { return cells.begin(); }
row_type* end() { return cells.end(); }
row_type const* begin() const { return cells.begin(); }
row_type const* end() const { return cells.end(); }
};
Just a cheesy demo to show it's genericity: Live on Coliru
#include <algorithm>
template<size_t N, typename T=int>
T test()
{
using std::begin;
using std::end;
typedef matrix<T, N, N*3+2> Mtx;
Mtx the_matrix;
size_t next_gen {};
auto gen = [&](){ return next_gen++ * 3.14; };
for(auto& row : the_matrix)
std::generate(begin(row), end(row), gen);
return std::accumulate(
begin(the_matrix), end(the_matrix), T{},
[](T accum, typename Mtx::row_type& row)
{
return accum + std::accumulate(begin(row), end(row), T{});
});
}
#include <iostream>
#include <string>
int main()
{
std::cout << test<3, int>() << "\n";
std::cout << test<3, double>() << "\n";
}
Upvotes: 1
Reputation:
I can get around this issue by converting everything to vectors of int vectors, but then I suffer a massive speed loss.
FAUX. That's just wrong. std::vector
is almost as fast as raw arrays. Do use vector<vector<int> >
.
However, if you still insist on raw arrays:
int **p = new int *[rows];
for (size_t i = 0; i < rows; i++)
p[i] = new int[columns];
Freeing:
for (size_t i = 0; i < rows; i++)
delete [] p[i];
delete [] p;
Upvotes: 0