std::variant's: Intelligent C++ Unions (C++17)
(Heavily from https://www.cppstories.com/2018/06/variant/)
Syntax
constexpr variant() noexcept(/* see below */); // (1) constexpr variant( const variant& other ); // (2) constexpr variant( variant&& other ) noexcept(/* see below */); // (3) template< class T > // (4) constexpr variant( T&& t ) noexcept(/* see below */);
template< class T, // (5)
class... Args >
constexpr explicit variant( std::in_place_type_t<T>,
Args&&... args );
template< class T, // (6)
class U,
class... Args >
constexpr explicit variant( std::in_place_type_t<T>,
std::initializer_list<U> il,
Args&&... args );
template< std::size_t I, // (7)
class... Args >
constexpr explicit variant( std::in_place_index_t<I>,
Args&&... args );
template< std::size_t I, // (8)
class U,
class... Args >
constexpr explicit variant( std::in_place_index_t<I>,
std::initializer_list<U> il,
Args&&... args );
The Currently Used Typed
We learn the currently used type via my_variant.index(), which returns an integer, or via std::holds_alternative<aType>(my_variant).
Getting the Value
You can use either std::get<its_type>(my_variant) or std::get<its_index>(my_variant).
If you write the wrong index or the wrong type, a bad_variant_access exception is thrown.
std::visit(visitor-function-object, element)
An example:
#include <iostream>
#include <variant>
#include <vector>
struct NodeA {};
struct NodeB {};
struct NodeC {};
using Nodes = std::variant<NodeA, NodeB, NodeC>;
struct Visitor {
void operator() (const NodeA&) { std::cout << "NodeA" << std::endl; }
void operator() (const NodeB&) { std::cout << "NodeB" << std::endl; }
void operator() (const NodeC&) { std::cout << "NodeC" << std::endl; }
};
int main() {
std::vector<Nodes> nodes = {
NodeA{},
NodeB{},
NodeA{},
NodeC{}
};
for (auto&& node : nodes)
std::visit(Visitor{}, node);
return 0;
}
Output:
NodeA NodeB NodeA NodeC
As you can see, all you need is a callable struct with overloads for required types. Note that you need to overload on all types that belong to Nodes or you’ll get a compiler error (like with pattern matching in other languages).