Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to extend a C++ structure/class with a void `null` or `empty` like element

Tags:

I am implementing a chess module as I learn C++. In the module I have (partially) implemented:

  • a Board class (grid, pieces, move methods etc.)
  • enumerated types Colour (BLACK/WHITE) and Rank (KING, QUEEN, ..., PAWN)

and

  • a 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?)

like image 865
Owen Avatar asked Feb 10 '19 07:02

Owen


1 Answers

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.
  • Extending the enums: I agree completely.
  • 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.
like image 197
besc Avatar answered Nov 15 '22 12:11

besc