A. choofe
A. choofe

Reputation: 3

How to declare a 2D vector consist 2D vectors?

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

Answers (2)

A. choofe
A. choofe

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

Caleth
Caleth

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

Related Questions