Over many years, I always find myself reconsidering this design, so I wanted to get some feedback on my solution to it.


I need a limited amount of objects = instances from a class, and I don't want to expose the option to create more. I also want easy access to them from everywhere, and operators like equal / not equal.
They need to be class instances, as they need to have methods, so a enum doesn't work.

(Simplified) Example:

Consider for example any chess-like game.

  1. There are three tile colors for the board needed, Lighter and Darker, and a different size tile where taken pieces are put. Also,
  2. the pieces have a color, typically White or Black; and I use NoColor for empty fields.

Both examples, each instance should know how to draw and serialize itself.

Obvious Option:

If I make a simple enum, the values cannot carry methods, so I end up with Draw and Serialize methods in some other class, which are basically an ugly switch/case.

My Solution:

I like to

  1. protect the constructor, and,
  2. create (public) static instances inside the class (C++17 now allows that even directly with inline).

'Each instance gets created with a const 'type' in it (basically a enum), set through the constructor.
Wherever I need the information, I use the const pointer to that static instance. This allows to easily _compare and assign them, and also allows calling their member functions as needed.
It even allows other games to derive from the class and add new static instances, for example, a three-player chess could add a Red instance inside a derived class. Because I hand around pointers to the base class everywhere, it is polymorphic, and the code doesn't have to handle the new color special in any way...

class Color
  Color(char c) : color{c} {}
  void Serialize(Archive& ar) const { ar << color; }

  const char color;

public:  // the only instances ever to exists; handed around by pointer
  inline const static Color NoColor{'X'};   // C++17 syntax, otherwise
  inline const static Color White{'W'};     // separate line in .cpp needed
  inline const static Color Black{'B'};

class Chess3Color : public Color
  Chess3Color(char c) : Color{c} {}

  inline const static Chess3Color Red{'R'};

Example Usage:

// create a White King
Piece* p = new WhiteKing{&Type::King, &Color::White, IDB_W_K_BMP};
if (p->IsColor(&Color::White)) { ... }
class Piece
  // Piece member function for serialization
  void Serialize(Archive& ar)
  // check if this piece is of a certain color
  // note that pointer compare is good enough!
  bool IsColor(const Color* c) { return color == c; }


I go back and forth in my mind between this being a code smell or a pretty good and clean solution. So is it a code smell?
How else would this be better designed?

I have read a lot about Singletons, and I don't think they would do me any good (aside from the fact that some people think they are a code smell too).

  • 2
    // which are basically an ugly switch/case. // It would be wrong to say that "all switch/case are ugly". There are ways to refactor switch/case so that they aren't ugly. Therefore, the beauty/ugly (the appropriateness) of each example of switch/case needs to be further analyzed. – rwong Apr 29 '18 at 3:49
  • 4
    Enum classes with methods are a nice-to-have in Java, but in C++ one should define non-member functions that take the enum as input argument and return data (property or attribute corresponding to each enum value) as needed. Then, a function that needs to perform behavior on the enum can consult these non-member functions. Classes would be appropriate if there are behavioral differences, i.e. they require different lines of code for each enum value. – rwong Apr 29 '18 at 3:52
  • 2
    In C++, non-member functions which provide behavior to enums can be looked up using argument dependent lookup (ADL). – rwong Apr 29 '18 at 4:07
  • 2
    Conceptually, the color is part of a piece's identity. It is not simply a property. In that sense, you should never really be checking to see if a piece is white or black, merely that it is the same color as another piece or not. There should be exactly two places where color is relevant and that's when you're drawing it and when you need to know whose turn it is. – Neil May 23 '18 at 6:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.