6

I'm trying to build a game which has a matrix of chars. I'm trying to use a vector of vectors to build my matrix. My game.h has this:

#ifndef GAME_H
#define GAME_H
// includes
using namespace std;
class Game 
{
  private:
    int row;
    int col;
    vector<vector<char>>* matrix;
    // other atributtes

  public:
    Game();
    ~Game(){}
    // some functions
};
#endif

And in my game.cpp:

Game::Game()
{
    this->col = 20;
    this->row = 20;
    // Initialize the matrix
    this->matrix = new vector<vector<char>>(this->col);
    for(int i = 0 ; i < this->col ; i++)
       this->matrix[i].resize(this->row, vector<char>(row));
    // Set all positions to be white spaces
    for(int i = 0 ; i <  this->col; i++)
      for(int j = 0 ; j < this->row ; j++)
        this->matrix[i][j] = ' ';
}

It's giving me an error:

error: no match for ‘operator=’ (operand types are ‘__gnu_cxx::__alloc_traits<std::allocator<std::vector<char> > >::value_type {aka std::vector<char>}’ and ‘char’)
     this->matrix[i][j] = ' ';
                          ^~~

in the line:

this->matrix[i][j] = ' ';

I would like to know what's causing this and how can I set everything to be a whitespace in my constructor?

  • You really ought to avoid `using namespace std` - it is a bad habit to get into, and [can silently change the meaning of your program](/q/1452721) when you're not expecting it. Get used to using the namespace prefix (`std` is intentionally very short), or importing *just the names you need* into the *smallest reasonable scope*. It's especially pernicious in header files, as you now inflict the problem on every source file that includes the header! – Toby Speight May 15 '18 at 09:54
  • BTW, did you read the error message? You're trying to assign a `char` to an object of type `std::vector`. Perhaps you meant `matrix` to be a vector of vector of char, rather than a pointer to a vector of vector of char. – Toby Speight May 15 '18 at 09:56
  • even if you somehow manage to tweak and make the above code work, in my opinion the multiple dereferencing of implicit ’this’ object will hurt the performance. Secondly your for loops that have loop index of type int doesn't match the loop index a std::vector class would have wanted for itself (if it were alive :P) and this will again cause implicit conversions slowing down the code further – ggulgulia May 15 '18 at 21:17

2 Answers2

5

Type of this->matrix is std::vector<std::vector<char>>*.

Type of this->matrix[i] is std::vector<std::vector<char>>

Type of this->matrix[i][j] is std::vector<char>.

Hence,

this->matrix[i][j] = ' ';

does not work.

Simplify your code. Change matrix to

std::vector<std::vector<char>> matrix; // Remove the pointer

Adjust your code accordingly.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

If I were you, I would have done it like this:

in games.hpp:

#ifndef GAME_H
#define GAME_H
// includes
template <class T>
class Game : public std::vector<std::vector<T>>
{
     private:
        int row;
        int col;

    public:
        Game();
       ~Game(){}
// some functions
};
#endif

in games.cpp

template<class T>
Game<T>::Game(int rr=20, int cc=20):
    row(rr), col(cc), std::vector<std::vector<T>>(rr, std::vector<T>(cc))
{
 //empty body   
}

This naturally will complicate the way you would have to access elements but it can be easily done by overloading the operator() that returns a reference to the position you want to access. Note by publicly inheriting the std::vector, we inherited all their operators and member functions and variables. Hence we also inherited the overloaded operator[] in std::vector class. Hence we can access any element by an overloaded operator as shown below:

template<class T>
T& Game<T>::operator()(int rr, int cc){
return this->operator[](rr)[cc];
}

In the return statement above, the first part calls the overloaded operator[] with an argument rr, which returns a vector object and on this vector object we call the overloaded operator[] once more by calling it with argument 'cc' as column index ( as we would do with a std::vector object[index] )

With this the code certainly looks elegant and professional :)

ggulgulia
  • 2,720
  • 21
  • 31
  • for scalable codes, i would use instead of 'int' for the types of row and columns, 'size_t' or better define a new type name 'size_type' that std::vector itself uses in it's definition (check out cpp reference) and the link below https://stackoverflow.com/questions/18385418/c-meaning-of-a-statement-combining-typedef-and-typename – ggulgulia May 15 '18 at 21:25
  • Thanks! Nice solution! – Carlos A. Jimenez Holmquist May 16 '18 at 00:49