Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Switch/case like function for tuples/pairs
#include <tuple>
#include <type_traits>
enum class A {
a, b
};
enum class B {
c, d
};
template <class T>
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
template <class L, class R>
struct Compare;
template <class L>
struct Compare<L, remove_cvref_t<decltype(std::ignore)>> {
bool operator()( const L &lhs, decltype(std::ignore) ) const { return true; }
};
template <class T>
struct Compare<T,T> {
bool operator()( const T &lhs, const T &rhs ) const {
return lhs == rhs;
}
};
template <class... L, class... R>
struct Compare<std::tuple<L...>,std::tuple<R...>> {
template <size_t... Is>
bool helper( const std::tuple<L...>& lhs, const std::tuple<R...> rhs, std::index_sequence<Is...> ) {
return std::min( Compare<remove_cvref_t<L>,remove_cvref_t<R>>()(std::get<Is>(lhs), std::get<Is>(rhs))... );
}
bool operator()( const std::tuple<L...>& lhs, const std::tuple<R...>& rhs ) {
return helper(lhs, rhs, std::make_index_sequence<std::max(sizeof...(L), sizeof...(R))>());
}
};
template <class T, class U>
bool isEqual( const T &t, const U &u ) {
return Compare<T,U>()(t, u);
}
template <class Tuple, class Case, size_t... Is>
bool tuple_case (const Tuple &t, Case&& c, std::index_sequence<Is...>) {
constexpr size_t action_idx = std::tuple_size<Case>::value-1;
if (isEqual(std::tie(std::get<Is>(t)...), std::tie(std::get<Is>(c)...))) {
std::get<action_idx>(c)();
return true;
}
return false;
}
template <class Tuple> void tuple_switch (Tuple &&t) {}
template <class Tuple, class Action, class... Actions>
void tuple_switch (Tuple &&t, Action&& first, Actions&&... others) {
using value_t = std::remove_reference_t<std::remove_cv_t<Tuple>>;
bool done = tuple_case(t, std::forward<Action>(first),
std::make_index_sequence<std::tuple_size<value_t>::value>());
if (!done)
tuple_switch(std::forward<Tuple>(t), std::forward<Actions>(others)...);
}
int a( const std::pair<A,B>& t ) {
int r = -1;
tuple_switch(t,
std::make_tuple(A::a, B::c, [&]() { r = 0; }),
std::make_tuple(A::a, B::d, [&]() { r = 1; }),
std::make_tuple(A::b, std::ignore, [&]() { r = 2; })
);
return r;
}
int foo() {
return a({A::a, B::c});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.