Question

Code like this:

#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 report:

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

My gcc version is 4.8.2 on fedora 20

Was it helpful?

Solution

The function foo is declared as:

int foo(int);

It has the function type int(int) (taking a parameter int and returning int).

However, the resulting callable returned by std::bind when you bind 3 to the first parameter has a different function type: int(), e.g.:

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

Solution

The template parameter specified when declaring the std::packaged_task should be specified as int(), e.g.:

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

Alternatively don't bind the parameter to 3 when constructing the std::packaged_task, instead supply it directly when creating the std::thread object:

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;

Furthermore

  • Make sure to call trd.join() before returning from function main.
  • When using std::thread also use the sleep function from the Standard Library instead of the non-portable sleep, e.g.:

    std::this_thread::sleep_for(std::chrono::seconds(1));
    
  • Also when using std::move you should include the header <utility> in case the other headers don't include it.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top