为什么 std::p ackaged_task<void()> 无效?
Why is std::packaged_task<void()> not valid?
使用MSVC2012,
以下代码将按照预期的进行编译和运行
std::packaged_task< int() > task( []()->int{ std::cout << "hello world" << std::endl; return 0; } );
std::thread t( std::move(task) );
t.join();
而下面的代码将无法编译和运行
std::packaged_task< void() > task( [](){ std::cout << "hello world" << std::endl; } );
std::thread t( std::move(task) );
t.join();
为什么会这样?
编辑:作为一种变通方法,可以使用std::promise在返回void 的函数上获得std::future
std::promise<void> promise;
auto future = promise.get_future();
std::thread thread( [](std::promise<void> &p){ std::cout << "hello world" << std::endl; p.set_value(); }, std::move(promise) );
future.wait();
请注意,在带有std::thread的vs2012库中有一个错误,它迫使您将promise作为l值引用传入并将其移入,如果您按值或按r值引用传递promise,它将不会编译。这可能是因为实现使用了std::bind(),但其行为与预期不符。
这是MSVC2012中的一个错误。MSVC2012附带的线程库实现中存在不少错误。我在博客中发布了一个部分列表,将其与我的商业广告Just::线程库进行了比较:http://www.justsoftwaresolutions.co.uk/news/just-thread-v1.8.0-released.html
这适用于gcc 4.7.2:
#include <thread>
#include <future>
#include <iostream>
int main() {
std::packaged_task< void() > task( [](){ std::cout << "hello world" << std::endl; } );
std::thread t( std::move(task) );
t.join();
std::packaged_task< int() > task2( []()->int{ std::cout << "hello world" << std::endl; return 0; } );
std::thread t2( std::move(task2) );
t2.join();
}
加上@WhozCraig的考古学暗示这可能是MSVC2012中的一个bug。
要解决此问题,请尝试使用struct Nothing {};
或nullptr_t
作为返回值?
MSVS 2013RC中仍然存在问题,但我在MS更正它的同时制作了这个临时补丁。它是void(…)的packaged_task的专门化,所以我建议将其放在头文件中,并将其包含在标准头文件之后。请注意,make_ready_at_thread_exit()未实现,并且某些函数尚未经过充分测试,使用风险自负。
namespace std {
template<class... _ArgTypes>
class packaged_task<void(_ArgTypes...)>
{
promise<void> _my_promise;
function<void(_ArgTypes...)> _my_func;
public:
packaged_task() {
}
template<class _Fty2>
explicit packaged_task(_Fty2&& _Fnarg)
: _my_func(_Fnarg) {
}
packaged_task(packaged_task&& _Other)
: _my_promise(move(_Other._my_promise)),
_my_func(move(_Other._my_func)) {
}
packaged_task& operator=(packaged_task&& _Other) {
_my_promise = move(_Other._my_promise);
_my_func = move(_Other._my_func);
return (*this);
}
packaged_task(const packaged_task&) = delete;
packaged_task& operator=(const packaged_task&) = delete;
~packaged_task() {
}
void swap(packaged_task& _Other) {
_my_promise.swap(_Other._my_promise);
_my_func.swap(_Other._my_func);
}
explicit operator bool() const {
return _my_func != false;
}
bool valid() const {
return _my_func != false;
}
future<void> get_future() {
return _my_promise.get_future();
}
void operator()(_ArgTypes... _Args) {
_my_func(forward<_ArgTypes>(_Args)...);
_my_promise.set_value();
}
void reset() {
swap(packaged_task());
}
};
}; // namespace std
相关文章:
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 无法访问嵌套类.类的使用无效
- 如果用户输入无效,如何使用字符串变量-C++重复输入命令
- 如何解决错误:SCIP C++中的 SCIP 阶段无效 <10>
- EASTL矢量<向量<int>>连续的
- 在没有参数列表的情况下使用模板名称"Event"无效,模板问题
- FFMPEG配置文件级别id大小无效
- 错误:从"int"到枚举c++的转换无效
- 如何修复此错误:className::className的无效使用
- 为什么将值返回函数传递给重载=运算符对运算符函数有效,而对其他运算符无效
- C++-模板嵌套类的引用初始化无效
- 错误:无效的预处理指令 #i 的意思是 #if?
- 多维数组 C++ 中数组下标的类型"int[int]"无效
- 在 C++ 中使用正则表达式错误时出现问题 括号表达式中的范围无效
- 从 'int' 到 'int*' CPP 的转换无效
- 如何接受 [ENTER] 键作为无效输入并发送错误消息
- 由于无效的 ValidateRgn() 子窗口不会收到WM_PAINT消息
- C++ PTHREADS - 无效转换无效*(*)()到无效*(*)(无效*)
- 声明为无效的变量或字段'...' Ardunio 编译器上的错误
- 数组下标的类型"float*[float]"无效