这个语法是什么意思,`class template <class r,=“”class =“”... args =“”> class name <r(args ...)>`

时间:2015-12-02 01:52:08

标签: c++ multithreading promise variadic-templates packaged-task

我一直在尝试更多关于c ++的多线程编程,我很难理解std::promise所以我开始在这个网站上寻找答案,而且很低,有人也有同样的像我这样的问题。但阅读答案让我更加困惑 这是答案中的代码,可能是std::packaged_task

的类似实现
template <typename> class my_task;

template <typename R, typename ...Args>
class my_task<R(Args...)>
{
    std::function<R(Args...)> fn;
    std::promise<R> pr;             // the promise of the result
public:
    template <typename ...Ts>
    explicit my_task(Ts &&... ts) : fn(std::forward<Ts>(ts)...) { }

    template <typename ...Ts>
    void operator()(Ts &&... ts)
    {
        pr.set_value(fn(std::forward<Ts>(ts)...));  // fulfill the promise
    }

    std::future<R> get_future() { return pr.get_future(); }

    // disable copy, default move
};

在此代码中,

1-这个语法是什么意思template <typename R, typename ...Args> class my_task<R(Args...)>,更具体地说,<R(Args...)>的目的是什么?

2-为什么课堂上会有一个额外的贬值?

谢谢

2 个答案:

答案 0 :(得分:3)

评论中有一些简短的讨论,1和2应该是两个单独的问题,但我认为它们只是同一个问题的两个方面,原因如下:

template <typename> class my_task;

template <typename R, typename ...Args>
class my_task<R(Args...)>; ....

第一个语句声明了一个模板,它以typename作为唯一的模板参数。第二个语句声明了该模板类的特化。

在此背景下:

 R(Args...)

将专门针对与函数匹配的任何typename。此模板特化将匹配传递typename的函数签名的任何模板实例。除非模板本身存在任何问题,否则此模板专业化将用于:

 my_task<int (const char *)>

或者,带有const char *参数并返回int的函数。模板专业化也将匹配:

 my_task<Tptr *(Tptr **, int)>

或者,带有两个参数Tptr **int的函数,并返回Tptr *(此处,Tptr是其他类)。

模板专精化不匹配:

 my_task<int>

或者

 my_task<char *>

因为它们不是功能签名。如果您尝试使用非函数typename实例化此模板,那么您将收到编译错误。为什么呢?

嗯,那是因为模板没有定义:

template<typename> class my_task;

不要认为这只是一个前瞻性宣言。它是一个采用模板参数的模板的前向声明,模板不会在任何地方定义。相反,模板声明允许后续的模板特化声明,它只匹配作为模板参数传递的特定类型。

这是一种常见的编程技术,用于限制可以与特定模板一起使用的typenameclass es的种类。模板只能与某个子集一起使用,而不是允许模板仅与任何typenameclass一起使用。在这种情况下,函数typename或签名。

它还使模板本身更容易显式引用 - 在本例中 - 模板参数的返回类型和参数类型。如果模板只有一个平淡无奇的单typename作为模板参数,则它无法轻松访问函数的返回类型或函数参数的类型。

答案 1 :(得分:2)

  

1:这种语法意味着什么template <typename R, typename ...Args> class my_task<R(Args...)>

这是类模板my_task的特化。名称后面的<R(Args...)>表示它专门用于该类型,该类型是一个函数。 R(Args...)是获取Args个参数并返回R的函数的类型。因此,例如my_task<void()> mt;会使Args成为空参数包,R将为void

  

2:为什么这个班级有前瞻声明?

声明了类,但与普通的前向声明不同,未定义非专用版本。此类仅适用于类型为函数的情况,因此如果有人尝试使用非函数的函数(如my_task<int>),则会出现有关未定义类型的错误。

my_task<void*(int, int)> mt1; //R = void*, Args = int, int
my_task<int> mt2; //error: use of undefined class