Search code examples
c++arraysenumsc++14stdarray

How to efficiently fill a 2D std::array with enum


I am trying to find an efficient and proper way to fill a 2D std::array matrix with an enum value. I am doing this:

#include <iostream>
#include <array>

template<class T, size_t ROW, size_t COL>
using Matrix = std::array<std::array<T, COL>, ROW>;

enum class State { FREE = 0, BUSY, BLOCKED, RESERVED };

int main() {
  const int mapX = 4;
  const int mapY = 9;

  // create a 5x10 2D array
  Matrix<State, mapY, mapX> MapMatrix;

  // fill array with State::RESERVED value
  for (int y = 0; y <= mapY; y++) MapMatrix[y].fill(State::RESERVED);

  std::cout << "MapMatrix contains:\n";

  for (int y = 0; y <= mapY; ++y) {
    for (int x = 0; x <= mapX; ++x) {
      std::cout << static_cast<int>(MapMatrix[x][y]) << " ";
    }
    std::cout << std::endl;
  }

  return 0;
}

Is the for loop I am doing the best way to fill the matrix with the enum value? Is there a way to fill the matrix during the declaration of Matrix<State, mapY, mapX> MapMatrix (like a constructor)?

Thanks!


Solution

  • I think that a loop based initialization is a good solution.

    But, just for fun, I propose you another solution std::index_sequence and template pack expansion based.

    A working example (with index corrected)

    #include <iostream>
    #include <utility>
    #include <array>
    
    template <typename T, std::size_t ROW, std::size_t COL>
    using Matrix = std::array<std::array<T, COL>, ROW>;
    
    enum class State { FREE = 0, BUSY, BLOCKED, RESERVED };
    
    template <typename T, std::size_t ... Rs, std::size_t ... Cl>
    Matrix<T, sizeof...(Rs), sizeof...(Cl)> initMat
       (T                          const & tVal,
        std::index_sequence<Rs...> const &,
        std::index_sequence<Cl...> const &)
     {
       auto col = std::array<T, sizeof...(Cl)>{ { ((void)Cl, tVal)... } };
    
       return Matrix<T, sizeof...(Rs), sizeof...(Cl)>
        { { ((void)Rs, col)... } };
     }
    
    int main()
     {
       constexpr std::size_t mapX =  5U;
       constexpr std::size_t mapY = 10U;
    
       // create a 5x10 2D array
       auto MapMatrix = initMat(State::RESERVED,
                                std::make_index_sequence<mapX>(),
                                std::make_index_sequence<mapY>());
    
       std::cout << "MapMatrix contains:\n";
    
       for ( auto y = 0U ; y < mapY ; ++y )
        {
          for ( auto x = 0U ; x < mapX ; ++x )
             std::cout << static_cast<int>(MapMatrix[x][y]) << " ";
    
          std::cout << std::endl;
        }
    
       return 0;
     }