std :: thread具有可移动的,不可复制的参数 [英] std::thread with movable, non-copyable argument

查看:93
本文介绍了std :: thread具有可移动的,不可复制的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下程序未在VS11 beta,gcc 4.5或clang 3.1中构建

The following program doesn't build in VS11 beta, gcc 4.5, or clang 3.1

#include <thread>
#include <memory>

int main() {
    std::unique_ptr<int> p;
    std::thread th([](std::unique_ptr<int>) {

    },std::move(p));
    th.join();
}

这是因为参数类型不可复制,但是实现尝试复制它.

This is because the argument type is not copyable, but the implementation attempts to copy it.

据我所知,该程序格式正确,应该可以运行.对std :: thread的要求似乎暗示可移动的不可复制参数在这里应该起作用.具体来说,它说可调用对象和每个参数都必须满足MoveConstructible要求,并且INVOKE(DECAY_COPY(std::forward<F>(f)),DECAY_COPY(std::forward<Args>(args))...)应该是有效表达式.

As far as I can tell, this program is well formed and should work. The requirements for std::thread seem to imply that movable, non-copyable arguments should work here. Specifically it says that the callable object and each argument shall satisfy the MoveConstructible requirements, and that INVOKE(DECAY_COPY(std::forward<F>(f)),DECAY_COPY(std::forward<Args>(args))...) shall be a valid expression.

在这种情况下,我认为表达式的效果类似于:

In this case I think expression works out to something like:

template <class T> typename std::decay<T>::type decay_copy(T&& v)
{ return std::forward<T>(v); }

std::unique_ptr<int> p;
auto f = [](std::unique_ptr<int>) {};

decay_copy(f)(decay_copy(std::move(p)));

我不认为这应该包含p的副本. gcc至少可以编译该表达式,尽管VS11不能.

And I don't think this is supposed to involve a copy of p. gcc at least can compile this expression, though VS11 does not.

  1. 我对要求有误吗,参数必须是可复制的?
  2. 该标准在实现复制参数方面是否留有余地?
  3. 还是我尝试的实施不符合要求?

推荐答案

摘自N3337的30.3.1.2第3和4段:

From 30.3.1.2, paragraph 3 and 4 of N3337:

template <class F, class ...Args> explicit thread(F&& f, Args&&... args);

template <class F, class ...Args> explicit thread(F&& f, Args&&... args);

要求: F ,并且 Args 中的每个 Ti 必须满足要求. INVOKE (DECAY_-COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...)(20.8.2)应该是有效的表达式.

Requires: F and each Ti in Args shall satisfy the MoveConstructible requirements. INVOKE (DECAY_-COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...) (20.8.2) shall be a valid expression.

效果:构造一个线程类型的对象.新的执行线程执行INVOKE (DECAY_-COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...),并在构造线程中评估对DECAY_COPY的调用.此调用的任何返回值都将被忽略. [注意:这意味着从调用 f 的副本中未引发的任何异常都将在构造线程中而不是新线程中抛出. — —尾注]如果INVOKE (DECAY_COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...)的调用因未捕获的异常终止,则应调用std :: terminate.

Effects: Constructs an object of type thread. The new thread of execution executes INVOKE (DECAY_-COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...) with the calls to DECAY_COPY being evaluated in the constructing thread. Any return value from this invocation is ignored. [ Note: This implies that any exceptions not thrown from the invocation of the copy of f will be thrown in the constructing thread, not the new thread. —end note ] If the invocation of INVOKE (DECAY_COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...) terminates with an uncaught exception, std::terminate shall be called.

是的,这应该有效.如果不是这样,那就是您的实现中的错误.

So yes, this should work. If it doesn't, then that's a bug in your implementation.

请注意,任何参数移动/复制都将在新线程上进行.您要将引用传递给另一个线程,因此需要确保在该线程启动之前它们仍然存在.

Do note that any parameter movement/copying will happen on the new thread. You're passing references to another thread, so you need to make sure that they still exist until that thread starts.

这篇关于std :: thread具有可移动的,不可复制的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆