I am implementing a chess module as I learn C++. In the module I have (partially) implemented:
Board
class (grid, pieces, move methods etc.)Colour
(BLACK/WHITE) and Rank
(KING, QUEEN, ..., PAWN)and
Piece
structure grouping colour and rank (BLACK KING,..., WHITE PAWN).I am now deciding how to represent the contents of a square on the board (grid). A square must either contain a Piece
(BLACK KING), or nothing. Options considered:
create a struct Square
containing two data members, {bool occupied ; Piece piece;}
, (possibly extending the Piece
class).
MY OBJECTION: Solution seems a little too heavy-weight, and in the event that the square is not occupied then the piece
member should be empty. I feel it may lead to exceptions being needed for some class methods, which should not be necessary.
extending the enumeration of Rank
or Colour
to include an empty option.
MY OBJECTION: Feels semantically inelegant, hacky and unnatural.
looking into other packages like std::optional
MY OBJECTION: For coding style and simplicity, I'd like to avoid the use of extra machinery. Would std::optional
even be suitable?
using NULL
or nullptr
to represent the state of an empty square
MY OBJECTION: Again, seems hacky. The contents of an empty square are NOT NULL
, nor the number 0
, should not be comparable to the number 26... but should be a fresh, new constant EMPTY_SQUARE.
None of these options quite seem to fit. Is there some more elegant way of extending a class (like Piece
) with other members (like EMPTY_SQUARE
) which has none of the original class's data members? (Are there any other options?)
A square on your chess board can either contain a piece or be empty. In more abstract terms you want to have either some specific thing or nothing at all. That’s exactly the use case std::optional
is made for. You cannot avoid extra machinery anyway because you need something to represent an empty square. In 2019-style C++ an optional type is a perfectly simple and idiomatic solution, especially when it comes from the standard library.
Regarding your other alternatives:
struct Square
: I agree with your objections, especially the question about what to put into the piece
member when the square is empty. In short: struct Square
is a naive, super-simple version of an optional.nullptr
: Sometimes a null pointer can be an appropriate representation of “nothing”. Usually you run into the issue when your implementation works with pointers anyway and you don’t want to introduce std::optional<T*>
– that would introduce an additional nothing-ish state along with its ambiguity. In general I do agree about avoiding null pointers wherever possible.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With