编译有关std :: future的错误

时间:2014-01-27 08:25:58

标签: c++ c++11 future

这样的代码:

#include <iostream>
#include <future>
#include <thread>
#include <unistd.h>

int foo(int n) {
    n = n*1000;
    sleep(1);
    return n;
}

int main(void) {
    std::packaged_task<int (int)> task(std::bind(foo, 3));
    std::future<int> f(task.get_future());

    std::thread trd(std::move(task));
    std::cout << f.get() << std::endl;

    return 0;
}

gcc报告:

In file included from /usr/include/c++/4.8.2/future:38:0,
                 from a.cpp:2:
/usr/include/c++/4.8.2/functional: In instantiation of ‘struct std::_Bind_simple<std::packaged_task<int(int)>()>’:
/usr/include/c++/4.8.2/thread:137:47:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = std::packaged_task<int(int)>; _Args = {}]’
a.cpp:16:33:   required from here
/usr/include/c++/4.8.2/functional:1697:61: error: no type named ‘type’ in ‘class std::result_of<std::packaged_task<int(int)>()>’
       typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                             ^   
/usr/include/c++/4.8.2/functional:1727:9: error: no type named ‘type’ in ‘class std::result_of<std::packaged_task<int(int)>()>’
         _M_invoke(_Index_tuple<_Indices...>)
         ^   
make: *** [a] Error 1

我的gcc版本在fedora 20上 4.8.2

1 个答案:

答案 0 :(得分:2)

函数foo声明为:

int foo(int);

它的函数类型为int(int)(参数int并返回int)。

但是,当std::bind绑定到第一个参数时,由3返回的结果可调用具有不同的函数类型:int(),例如:

auto func = std::bind(foo, 3) // Bind 3 to the first parameter.
func();                       // Calling func requires no parameter.

解决方案

声明std::packaged_task时指定的模板参数应指定为int(),例如:

std::packaged_task<int()> task{std::bind(foo, 3)};

或者在构建3时不要将参数绑定到std::packaged_task,而是在创建std::thread对象时直接提供参数:

std::packaged_task<int(int)> task{foo}; // Don't bind 3
auto f = task.get_future();

std::thread trd{std::move(task), 3};    // Supply 3 here instead.
std::cout << f.get() << std::endl;

此外

  • 确保在从函数trd.join()返回之前致电main
  • 使用std::thread时,也请使用标准库中的睡眠功能,而不是非便携式sleep,例如:

    std::this_thread::sleep_for(std::chrono::seconds(1));
    
  • 同样在使用std::move时,您应该包含标题<utility>,以防其他标题不包含它。