-
-
Save ayles/9d431de6e7d202fa3a4409a33ef71d52 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 <string> | |
struct zero {}; | |
struct one {}; | |
struct two {}; | |
template<typename T> | |
struct is_same; | |
template<> | |
struct is_same<std::tuple<zero>> { | |
static bool check(int *p) { | |
return *p == 0; | |
} | |
static zero cast(int *p) { | |
return zero {}; | |
} | |
}; | |
template<> | |
struct is_same<std::tuple<one>> { | |
static bool check(int *p) { | |
return *p == 1; | |
} | |
static one cast(int *p) { | |
return one {}; | |
} | |
}; | |
template<> | |
struct is_same<std::tuple<two>> { | |
static bool check(int *p) { | |
return *p == 2; | |
} | |
static two cast(int *p) { | |
return two {}; | |
} | |
}; | |
template<typename K, typename Q, typename ...Args> | |
struct is_same<std::tuple<K, Q, Args...>> { | |
static bool check(int *p) { | |
return is_same<std::tuple<K>>::check(p) && is_same<std::tuple<Q, Args...>>::check(p + 1); | |
} | |
}; | |
template<typename F> | |
struct f_info; | |
template<typename R, typename ...Args> | |
struct f_info<R(Args...)> { | |
using return_type = R; | |
using arguments = std::tuple<Args...>; | |
using pointer_type = R (*)(Args...); | |
}; | |
template<typename R, typename ...Args> | |
struct f_info<R(*)(Args...)> : f_info<R(Args...)> {}; | |
template<typename R, typename ...Args> | |
void call_f(R (&f)(Args...), int *p) { | |
f((is_same<std::tuple<Args>>::cast(p))...); | |
} | |
template<typename F> | |
bool try_call(F &f, int *p) { | |
if (is_same<typename f_info<F>::arguments>::check(p)) { | |
call_f(f, p); | |
std::cout << "Called " << typeid(F).name() << std::endl; | |
return true; | |
} else { | |
std::cout << "Error calling " << typeid(F).name() << std::endl; | |
return false; | |
} | |
} | |
template<typename F, typename Q, typename ...Args> | |
bool try_call(F &f, Q &q, Args&... a, int *p) { | |
return try_call<F>(f, p) || try_call<Q, Args...>(q, a..., p); | |
} | |
void handler_a(two, two, two) { | |
std::cout << "A" << std::endl; | |
} | |
void handler_b(two, two, zero) { | |
std::cout << "B" << std::endl; | |
} | |
int main() { | |
int a[] = { 2, 2, 0 }; | |
try_call(handler_a, handler_b, a); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment