That's my demo to illustrate:
#include <iostream>
#include <ostream>
#include <utility>
template <typename T>
bool f(int) {
__builtin_unreachable();
}
template <>
bool f<int>(int) {
return true;
}
template <>
bool f<float>(int) {
return true;
}
template <>
bool f<double>(int) {
return false;
}
enum class Ops { OR, AND, VOID };
template <Ops Op, typename T, typename... Ts>
bool call_for_multi_type(int arg) {
if constexpr (sizeof...(Ts) == 0) {
return f<T>(arg);
} else {
if constexpr (Op == Ops::OR) {
return f<T>(arg) || call_for_multi_type<Op, Ts...>(arg);
} else if constexpr (Op == Ops::AND) {
return f<T>(arg) && call_for_multi_type<Op, Ts...>(arg);
} else if constexpr (Op == Ops::VOID) {
return (f<T>(arg), call_for_multi_type<Op, Ts...>(arg));
} else {
__builtin_unreachable();
}
}
}
int main() {
std::cout << call_for_multi_type<Ops::AND, int, double, float>(1);
std::cout << call_for_multi_type<Ops::OR, int, float, double>(1);
std::cout << call_for_multi_type<Ops::OR, int, float>(1);
std::cout << call_for_multi_type<Ops::OR, double>(1);
return 0;
}
And now I want to make a new function based on it, which let f
also could be specific in compile stage. That's to say, I have a dozen of template functions, not only f
. and I can change my call from
call_for_multi_type<Ops::AND, int, double, float>(1)
to
call_for_multi_type<func1, Ops::AND, int, double, float>(1)
or
call_for_multi_type<func2, Ops::AND, int, double, float>(1)
and all of them have different signatures.