Developer Tips

View Company GitHub Profile

29 February 2020

Create a new type when using std::variant

by Zhihao Yuan

Let’s say you want to model a game of rock paper scissors, where a hand is one of rock, paper, and scissors:

class rock {};
class paper {};
class scissors {};
using hand = std::variant<rock, paper, scissors>;

Ignoring the fact that this hand type comes with heavily overloaded constructors and you can only add free functions, a troublesome issue is that the type-name std::variant<rock, paper, scissors> will appear everywhere in debuggers and linkers in place of hand.

A more flexible way is to define a new type for it:

struct hand : std::variant<rock, paper, scissors> {};

You may pass *this directly to std::visit without casting it to the base class type. And if you do need to refer to the base class type, you don’t have to type it again:

struct hand : std::variant<rock, paper, scissors>
    static_assert(sizeof(variant) > 1);

Here, “variant” is an injected-class-name in the class scope of hand. It already aliases “std::variant<rock, paper, scissors>.”

tags: cplusplus - variant - injected-class-name