I am looking for a way to pass a generic (constexpr, obviously) function to a template. It has to be able to take any amount of parameters, without using a lambda. This is what I have so far:
template<typename T, T(*FUNC)()> struct CALL
{
static inline constexpr decltype(FUNC()) EXEC()
{
return FUNC();
}
};
This however only works if the passed function takes no parameters. Is there a way to make the template accept ANY constexpr function? Passing a std::function does not seem to work.
I suppose the key is variadic template parameters, but I have no idea how to take advantage of them in this situation.
If I understand correctly what you are trying to achieve, you can use a template function rather than a template class with a static function:
#include <iostream>
template<typename T, typename... Ts>
constexpr auto CALL(T (*FUNC)(Ts...), Ts&&... args) -> decltype(FUNC(args...))
{
return FUNC(std::forward<Ts>(args)...);
}
constexpr double sum(double x, double y)
{
return (x + y);
}
int main()
{
constexpr double result = CALL(sum, 3.0, 4.0);
static_assert((result == 7.0), "Error!");
return 0;
}
template<int... I>
struct with
{
template<int F(decltype(I)...)>
struct call
{
static constexpr int value = F(I...);
};
};
constexpr int f(int i) {return i;}
constexpr int g(int i, int j) {return i + j;}
int main()
{
int u = with<0>::call<f>::value;
constexpr int v = with<0, 1>::call<g>::value;
}
Note, this has some of the limitations as in your previous question which I answer with std::integral_constant
. But a constexpr
double
value could still be generated from non-type template arguments at compilation time.
#include <iostream>
template<typename T, T... v>
struct with
{
template<typename R, R f(decltype(v)...)>
struct call
{
static constexpr R value = f(v...);
};
};
#define AT_COMPILATION(f, x, ...) with<decltype(x), x, ##__VA_ARGS__>::call<decltype(f(x, ##__VA_ARGS__)), f>::value
constexpr long f(long i) {return i;}
constexpr double g(int i, int j) {return static_cast<double>(i) / j;}
int main()
{
constexpr double u = with<long, 0L>::call<decltype(f(0L)), f>::value;
std::cout << with<int, 5, 2>::call<double, g>::value << std::endl;
constexpr double v = AT_COMPILATION(f, 0L);
std::cout << AT_COMPILATION(g, 5, 2) << std::endl;
}