函数式模板语法

Function-style template syntax

我正在尝试编写一个相当简单的 class,它接受一个函数和一些参数,并且可以在稍后使用参数执行该函数。

目前,这是我的代码:

template<typename R, typename... Args>
class Delayed
{
public:
    using FunctionT = std::function<R(Args...)>;

    Delayed(FunctionT func, Args... args) : func(func), args(std::forward<Args>(args)...)
    {

    }

private:
    FunctionT func;
    std::tuple<Args...> args;
};

int main()
{
    std::function<double(double)> doubleMe = [](double x) { return x * 2.0; };

    //Works
    Delayed<double, double> delayed1(doubleMe, 2.0);

    //Doesn't work
    Delayed<double(double)> delayed2(doubleMe, 2.0);
}

问题是,当我将 double(double) 作为参数传递时,R 不是 doubleArgsdouble,而是传递 double(double)RArgs.

什么都没有

According to cppreferencestd::function 的模板参数是 template< class R, class... Args >。因此,如果我给它 A(B,C),它将为参数 R 传递 A,为可变参数 Args 传递 B,C。但是,当我将其传递给我的 class 时,它会为 R 传递 A(B,C),而不会为可变参数 Args.

传递任何内容

这个函数语法应该如何使用,为什么它适用于 std::function 而不是我的 class?

So if I give it A(B,C), it will pass A for the argument R and B,C for the variadic argument Args.

是的,但不是你想的那样。如果仔细观察,您会发现 std::function 部分特化了任何函数类型:

template<typename R, typename... Args>
class function<R(Args...)>;
//            ^^^^^^^^^^^^

你可以把它想象成非常原始的模式匹配。如果用int(int, double)实例化function,那么RintArgsint, double是有道理的。如果(部分)专业化比 catch-all 通用主模板更匹配,则选择它,这就是这里发生的情况。

记住:double(double) 是一个类型,它是一个函数。没有涉及它的任何特殊规则。所以,在你的情况下,你会这样做:

template<typename R, typename... Args>
class Delayed<R(Args...)> : public Delayed<R, Args...> {
  //         ^^^^^^^^^^^^
  //       partially specialize to decompose function types

  // We need to inherit constructors (only).
  using Delayed<R, Args...>::Delayed;
};

希望它能消除困惑。