Is it possible to parameterize non-type template arguments? I'm trying to generate a thunk that forwards its arguments to one of two compile time constant functions based on some runtime check, to get something hopefully along the lines of this:
#include <stdlib.h>
int a(int, int, char) {
return 0;
}
int b(int, int, char) {
return 0;
}
// This doesn't work
template<typename ReturnType, typename... Params>
template<ReturnType (*first)(Params...), ReturnType (*second)(Params...)>
ReturnType coin_flip(Params... params) {
if (rand() % 2) {
return first(params...);
} else {
return second(params...);
}
}
int main() {
return coin_flip<a, b>(1, 2, '3');
}
There is a workaround which uses type template parameters (via std::integral_constant
) and macros:
#include <type_traits>
template <typename, typename>
struct coin_flip;
template
<
typename ReturnType,
typename... Params,
ReturnType (*first)(Params...),
ReturnType (*second)(Params...)
>
struct coin_flip
<
std::integral_constant<ReturnType (*)(Params...), first>,
std::integral_constant<ReturnType (*)(Params...), second>
>
{
static
ReturnType call(Params&&... params) {
if (rand() % 2) {
return first(std::forward<Params>(params)...);
} else {
return second(std::forward<Params>(params)...);
}
}
};
#define FUNCTION_CONSTANT(f) std::integral_constant<decltype(&f), f>
#define COIN_FLIP(first, second, ...) \
coin_flip<FUNCTION_CONSTANT(first), FUNCTION_CONSTANT(second)>::call(__VA_ARGS__)
Example of using:
std::cout << COIN_FLIP(a, b, 1, 2, '3') << std::endl;