There are not only struct
and class
primitives in C++ that enable us to compose types. If we want to express that some variable can hold either some type A
or a type B
(or C
, or whatever), we can use union
. The problem with unions is that they cannot tell us they were actually initialized to which of the types that they can hold.
Consider the following code:
union U { int a; char *b; float c; }; void func(U u) { std::cout << u.b << '\n'; }
If we call the func
function with a union that was initialized to hold an integer via member a
, there is nothing that prevents us from accessing it, as if it was initialized to store a pointer to a string via member b
. All kinds of bugs can be spread from such code. Before we start to pack our union with an auxiliary variable that tells us to what it was initialized in order to gain some safety, we can directly use std::variant
, which came with C++17.
The variant
is kind of the new-school...