将任何函数作为模板参数传递?

时间:2013-01-12 21:08:36

标签: c++ templates c++11 function-pointers variadic-templates

我正在寻找一种将通用(constexpr,显然)函数传递给模板的方法。它必须能够在不使用lambda的情况下获取任何数量的参数。这就是我到目前为止所做的:

template<typename T, T(*FUNC)()> struct CALL
{
    static inline constexpr decltype(FUNC()) EXEC()
    {
        return FUNC();
    }
};

但是,只有传递的函数不带参数时才有效。有没有办法让模板接受任何constexpr功能?传递std ::函数似乎不起作用。 我想关键是可变参数模板参数,但我不知道在这种情况下如何利用它们。

2 个答案:

答案 0 :(得分:6)

如果我理解你想要实现的目标,你可以使用模板函数而不是带有静态函数的模板类:

#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;
}

答案 1 :(得分: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;
}

请注意,这有一些限制,例如我previous question answer std::integral_constant。但是在编译时仍然可以从非类型模板参数生成constexpr double值。

#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;
}