Last active
September 22, 2016 17:28
-
-
Save amaiorano/49b2f50d133341148e60fcd74647da10 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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