Skip to content

Instantly share code, notes, and snippets.

@amaiorano
Last active September 22, 2016 17:28
Show Gist options
  • Save amaiorano/49b2f50d133341148e60fcd74647da10 to your computer and use it in GitHub Desktop.
Save amaiorano/49b2f50d133341148e60fcd74647da10 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <experimental/variant.hpp>
using namespace std::experimental;
using namespace std;
// Add missing variant_size and variant_size_v (Submitted a PR for this)
template <class VariantType>
struct variant_size
{
static constexpr auto value = std::experimental::fundamentals_v3::tuple_size<VariantType>::value;
};
template <class VariantType>
constexpr std::size_t variant_size_v = variant_size<VariantType>::value;
namespace match_detail
{
template <int variant_index, typename VariantType, typename OneFunc>
constexpr void match(const VariantType& variant, OneFunc func)
{
assert(variant.index() == variant_index);
func(get<variant_index>(variant));
}
template <int variant_index, typename VariantType, typename FirstFunc, typename SecondFunc, typename... Rest>
constexpr void match(const VariantType& variant, FirstFunc func1, SecondFunc func2, Rest... funcs)
{
if (variant.index() == variant_index)
{
match<variant_index>(variant, func1); // Call single func version
return;
}
return match<variant_index + 1>(variant, func2, funcs...);
}
}
template <typename VariantType, typename... Funcs>
void match(const VariantType& variant, Funcs... funcs)
{
static_assert(sizeof...(funcs) == variant_size_v<VariantType>, "Number of functions must match number of variant types");
match_detail::match<0>(variant, funcs...);
}
int main()
{
struct Alive
{
const char* name = "Alive";
int health = 100;
};
struct Hurt
{
Hurt(Alive& fromAlive) {}
const char* name = "Hurt";
};
struct Dead
{
const char* name = "Dead";
};
struct NewState {};
variant<Alive, Hurt, Dead> state;
//variant<Alive, Hurt, Dead, NewState> state; // Fails to compile (mismatched number of states vs functions)
state = Alive{};
match(state,
[](auto& alive) { cout << alive.name << ", health is " << alive.health << endl; },
[](auto& hurt) { cout << hurt.name << endl; },
[](auto& dead) { cout << dead.name << endl; });
state = Hurt{ get<Alive>(state) };
match(state,
[](auto& alive) { cout << alive.name << ", health is " << alive.health << endl; },
[](auto& hurt) { cout << hurt.name << endl; },
[](auto& dead) { cout << dead.name << endl; });
state = Dead{};
match(state,
[](auto& alive) { cout << alive.name << ", health is " << alive.health << endl; },
[](auto& hurt) { cout << hurt.name << endl; },
[](auto& dead) { cout << dead.name << endl; });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment