Variants are C++’s union solution. Since C style unions in C++ can only support basic types, they are quite limited. Unions and variants can be pretty good for things like event data, or storing json (or any other interchange format) data. You might choose to use a variant to pass data around a callback system.
But if you’ve ever cracked open Boost’s variant or looked at some of the other variants out there it can be hard to understand what’s going on under the hood. And there is usually a lot going on as there are a few edge cases you need to consider. However even fundamentally understanding what is going on can be a challenge as templates can quickly become hard to read.
Type Agnostic Data Store
You might have already done something like this for getting data out of an xml/json etc.
We just have a chunk of memory that we use to dump various different data types into.
This way we can push what we want into data_store as long as its within the maximum size of the data_store.
Well really that’s half way to a simple variant class. Extracting out this logic we can very quickly make a simple generic variant.
A Simplistic Variant
We can use templates to get and set the data in the data store, and std::aligned_union will allow us to get the size of the biggest type we might need to store.
To use the variant we need to pass in the types that it should support. This way the template can figure out how much space is required.
The variant’s size will be the size of its biggest element, which is something to be aware of.
And thats about it.
Is That Really It?
Well no, not really. I’ve left out a lot of details so I could show the barebones of how a variant works, without getting bogged down in a lot of detail (There are a bunch of posts that go into that detail). Most notably whats missing is type checking. You really want some type_id system to be able to force an error if you are trying to get a float from an std::string etc.
However this is a good starting point for creating your own variant, it’s mine anyway.