【问题标题】:What does this syntax mean, `class template <class R, class ...Args> class name<R(Args...)>`这个语法是什么意思,`class template <class R, class ...Args> class name<R(Args...)>`
【发布时间】:2015-12-02 01:52:07
【问题描述】:

我一直在尝试更多关于 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 &lt;typename R, typename ...Args&gt; class my_task&lt;R(Args...)&gt;,更具体地说,&lt;R(Args...)&gt; 的目的是什么?

2- 为什么要对班级进行前向减速?

谢谢

【问题讨论】:

  • 哇哇,每个问题一个问题
  • 我应该把它分成3个不同的问题吗?它们似乎都密切相关,尤其是 1 和 2
  • 是的,我想是的。您在这里有三个非常好的问题的开头,但不应将它们混为一谈,它们也可以通过一些充实和研究来完成。相关不等于相同。
  • 我会研究它们,但我不知道要研究什么,我不能在谷歌中准确输入class template &lt;class R, class …Args&gt; class name&lt;R(Args…)&gt;,它会知道在说什么

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


【解决方案1】:

在 cmets 中有一些简短的讨论,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;

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

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

它还使模板本身更容易显式引用(在这种情况下)模板参数的返回类型和参数类型。如果模板只是一个乏味的、单一的typename作为模板参数,它就不能轻易地访问函数的返回类型,或者函数参数的类型。

【讨论】:

  • 非常感谢,现在一切都说得通了。我知道这是一种专业化语法,但我以前从未见过这样的语法。
【解决方案2】:

1:这个语法是什么意思template &lt;typename R, typename ...Args&gt; class my_task&lt;R(Args...)&gt;

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

2:为什么类有前向声明?

类已声明,但与普通的前向声明不同,未定义非专用版本。此类仅适用于类型为函数的情况,因此如果有人尝试使用非函数的内容(如my_task&lt;int&gt;),则会给出类型未定义的错误。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-28
    • 1970-01-01
    • 1970-01-01
    • 2020-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多