Skip to content

Instantly share code, notes, and snippets.

@ayles

ayles/main.cpp Secret

Created August 31, 2019 20:05
Show Gist options
  • Save ayles/9d431de6e7d202fa3a4409a33ef71d52 to your computer and use it in GitHub Desktop.
Save ayles/9d431de6e7d202fa3a4409a33ef71d52 to your computer and use it in GitHub Desktop.
#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