1

I was trying to create a user-defined container type with using and private members in the class, which are not compile-time constants. The is not valid and complained by the compiler. Those private member constants will only be initialized at runtime. Is there such a remedy for this kind of scenario?

#include <vector>
#include <array>
#include <string>
#include <iostream>


class SudokuBoard
{
private:
    Board _board_data;
    int _BOX_SIZE;
    int _BOARD_SIZE;
    const int _MAX_VALUE = _BOARD_SIZE;
    const int _NUM_CONSTRAINTS = 4;
    
public:
    template <class T, int ROW, int COL>
    using Matrix = std::array<std::array<T, COL>, ROW>;
    using CoverMatrix = Matrix<int, _BOARD_SIZE * _BOARD_SIZE * _MAX_VALUE, _BOARD_SIZE * _BOARD_SIZE * _NUM_CONSTRAINTS>;
    using Board = Matrix<int, _BOARD_SIZE, _BOARD_SIZE>;

    SudokuBoard(const std::string& filename);

    void set_board_data(int row, int col, int num) { _board_data[row][col] = num; }
    int get_board_data(int row, int col) const { return _board_data[row][col]; }
    Board get_board_data() const { return _board_data; }
    int at(int row, int col) const { return _board_data[row][col]; }
    
    // Prints the Sudoku board
    friend void print_board(const SudokuBoard& board);
    friend std::ostream& operator<< (std::ostream &out, const SudokuBoard& board);

    int indexInCoverMatrix(int row, int col, int num);
    int createBoxConstraints(CoverMatrix coverMatrix, int header);
    int createColumnConstraints(CoverMatrix coverMatrix, int header);
    int createRowConstraints(CoverMatrix coverMatrix, int header);
    int createCellConstraints(CoverMatrix coverMatrix, int header);
    void createCoverMatrix(CoverMatrix coverMatrix);
    void convertToCoverMatrix(Board board, CoverMatrix coverMatrix);
};
livemyaerodream
  • 890
  • 6
  • 19
  • 1
    Template parameters must be known at compile-time. If you have a limited set of parameters, you can specify all the valid options at compile-time and let the user choose which one to use at run-time. – super Aug 06 '21 at 14:05
  • If the values are known only at run-time, they obviously cannot be used in templates. C++ templates are purely compile-time concept in contract to C#. – Quimby Aug 06 '21 at 14:05
  • By definition a constant must be initialized at compile time. If it is initialized at run time, it is only a const variable and cannot be used where a true constant (or constexpr) is expected. – Serge Ballesta Aug 06 '21 at 14:05
  • @SergeBallesta not in C++, that is why C++11 introduced `constexpr` – Marek R Aug 06 '21 at 14:12
  • Please post a [mre]. Your `Board` class is missing – Superlokkus Aug 06 '21 at 14:14
  • 1
    @MarekR : C++11 has now been around for more than 10 years... When I see a question tagged C++ with no precision I assume at least C++14 or C++17... – Serge Ballesta Aug 06 '21 at 14:15
  • When the size is only known at runtime, dont use an array whose size must be known at compile time, use a `std::vector` – 463035818_is_not_an_ai Aug 06 '21 at 14:26
  • identifiers starting with `_` followed by a capital letter are reserverd (https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier). You better avoid them, because with some bad luck they migt clash and you'll get weird bugs – 463035818_is_not_an_ai Aug 06 '21 at 14:31
  • @SergeBallesta You have missed my point, I meant `const` is not same as `constexpr` and `const` can be evaluated at runtime. Simply your statement was not precise. – Marek R Aug 06 '21 at 14:56

1 Answers1

0

The first issue you get, compiling this, with a placeholder class Board{}; is something like:

Compilation failed For more information see the output window x86-64 clang 12.0.1 - 405ms

:23:37: error: invalid use of non-static data member '_BOARD_SIZE' using CoverMatrix = Matrix;

What this tells you is that the compiler needs to know at compile them about the sizes and types of your templates.

A first step is to make them static const. That way, the compiler knows at compile time:

static const int _BOARD_SIZE = 9;
static const int _MAX_VALUE = _BOARD_SIZE;

(constexpr give you other, more modern, options but this is a starting point)

Then, you'll probably want to have your SudokuBoard class itself templated on some type T. But I can't get there as you didn't provide the Board class.

Jeffrey
  • 11,063
  • 1
  • 21
  • 42