Reputation: 3
This is confusing me in c++ (17) I want to declare a 2 dimension vector with any size which each member is again a 2D vector itself. I want to make empty vectors with known size. In fact I want its size to be set at declaration. For a better picture , imagine a classic sodoku puzzle with 9 houses in 3x3 grid which each house has 9 cells in 3x3 grid.
#include<iostream>
#include <vector>
using cell_t = std::vector<std::vector<int> >;
using board_t = std::vector<std::vector<cell_t> >;
cell_t temp(3, std::vector<int>(3)); //this would be a 2D vector member
Now the problem:
board_t test(3,std::vector<cell_t>(3,std::vector<int>(3)));//this won't work
compiler errors: Error C2440 '': cannot convert from 'initializer list' to 'std::vector>' Training2 main.cpp
and
Error (active) E0289 no instance of constructor "std::vector<_Ty, _Alloc>::vector [with _Ty=cell_t, _Alloc=std::allocator]" matches the argument list Training2 main.cpp 91
I wonder what do I missed? I know I can make it happen with a temporary cell_t
like:
cell_t temp(3, std::vector<int>(4));
board_t test(3,std::vector<cell_t>(3,temp));
but I rather prefer using unknown object.
In the other hand I know how to use resize()
or push_back()
in favor to resize vectors to desirable sizes. But isn't it more faster to make this happen at the declaration rather than doing additional processes? because I want empty vectors
Upvotes: 0
Views: 250
Reputation: 3
It turns out that the problem is to define a vector of cell_t
declaration.
board_t test(3,std::vector<cell_t>(3,std::vector<int>(3)))
// @a^^^^^^^ @b^^^^^^^^^^^^^^^
@a we have a vector of cell_t
but @b we describe a 'vector of int'
that's the problem.
we should go by cell_t(3,std::vector<int>(3)
instead of @b
it should goes like this:
board_t test(3, std::vector<cell_t>(3, cell_t(3, std::vector<int>(3))));
Upvotes: 0
Reputation: 62531
Your current type definitions make it easy to have non-square cells and boards, and you have lots of indirection to reach an element. If you encapsulate that in a class, your initialisers can lose much of the repetition you currently have.
struct index_t {
std::size_t x;
std::size_t y;
};
template <typename T>
class square_matrix {
std::size_t size;
std::vector<T> elems;
std::size_t position(index_t index) { return index.x + (index.y * size); }
public:
square_matrix(std::size_t size, T elem = {}) : size(size), elems(size * size, elem) {}
T& operator[](index_t index) { return elems[position(index)]; }
const T& operator[](index_t index) const { return elems[position(index)]; }
};
using cell_t = square_matrix<int>;
using board_t = square_matrix<cell_t>;
board_t test(3, cell_t(3));
Upvotes: 3