函数式模板语法

时间:2018-03-29 07:41:52

标签: c++ templates c++14 variadic

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

目前,这是我的代码:

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时,它会通过{{1} } {}} double(double)R

According to cppreferenceArgs的模板参数为std::function。因此,如果我给它template< class R, class... Args >,它将为参数A(B,C)传递A并为变量参数R传递B,C。但是当我将它传递给我的班级时,它会Args传递给A(B,C),并且不会为可变参数R传递任何内容。

该函数语法应该如何使用?为什么它适用于Args而不是我的班级?

1 个答案:

答案 0 :(得分:2)

  

因此,如果我给它A(B,C),它将为参数A传递R,为变量参数B,C传递Args

是的,但不是出于您的想法。仔细观察,您会发现std::function部分专门针对任何函数类型:

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

你可以把它想象成非常原始的模式匹配。如果您使用function实例化int(int, double),那么Rint,而Argsint, 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;
};

希望它能解决困惑。