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