Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What should I use instead of void as one of the alternative types in an variant?

I want to have a variant which may contain type Foo, (disjoint) type Bar, or nothing. Well, naturally, I was thinking of using std::variant<Foo, Bar, void> - but this doesn't seem to work. That is, you can define this type, but if you try to instantiate this you'll fail (GCC 8.2).

So what do I use instead? Some kind of empty struct?

like image 492
einpoklum Avatar asked Nov 02 '18 22:11

einpoklum


1 Answers

What you really want is a type among the alternatives which has a single possible value - not void, which has no possible values (and is problematic in other ways). In other words: A unit type instead of a bottom type.

The standard library has defined, as part of <variant>, a "unit type" for this use case: std::monostate (and yes, it's essentially an empty struct). Use it.

Example:

#include <variant>

using Foo = int;
using Bar = double;

int main() {
    std::variant<std::monostate, Foo, Bar> v; 
    v = Foo{}; 
}

Note that, unlike in the question, the single-possible-value type is the first alternative; this allows the variant to be default-constructible even if Foo isn't. Also, it's potentially cheaper/faster to construct the variant this way than constructing a Foo, even if it is default-constructible.

like image 68
einpoklum Avatar answered Nov 08 '22 18:11

einpoklum