kei1aeh5quahQu4U
kei1aeh5quahQu4U

Reputation: 153

std::packaged_task compile error w/ gcc 4.6

I'm trying to launch a function in a thread using std::packaged_task

Query query; /* protobuf object */        

/* fill Query object */

std::packaged_task<SearchResults(Query&)> task([](Query& q) ->SearchResults {
    index::core::Merger merger;
    return merger.search(q);
    });

std::future<SearchResults> ftr = task.get_future();
std::thread(std::move(task),query).detach();

Edit2: Updated the code again to fix errors and included the full error message.

g++-4.6 (on Ubuntu 10.04) is unable to compile the code:

In file included from /usr/include/c++/4.6/memory:80:0,
              from ../src/net/QueryConnection.cpp:8:
/usr/include/c++/4.6/functional: In instantiation of ‘std::_Bind_result<void, 
std::packaged_task<SearchResults(Query&)>(Query)>’:
/usr/include/c++/4.6/thread:135:9:   instantiated from ‘std::thread::thread(_Callable&&, 
_Args&& ...) [with _Callable = std::packaged_task<SearchResults(Query&)>, _Args = 
{Query&}]’
../src/net/QueryConnection.cpp:77:36:   instantiated from here
/usr/include/c++/4.6/functional:1365:7: error: ‘std::_Bind_result<_Result, 
_Functor(_Bound_args ...)>::_Bind_result(const std::_Bind_result<_Result, 
_Functor(_Bound_args ...)>&) [with _Result = void, _Functor =   
std::packaged_task<SearchResults(Query&)>, _Bound_args = {Query}, 
std::_Bind_result<_Result, _Functor(_Bound_args ...)> = std::_Bind_result<void, 
std::packaged_task<SearchResults(Query&)>(Query)>]’ declared to take const reference, 
but implicit declaration would take non-const
Build error occurred, build is stopped

I've read that this is maybe due to a bug: gcc-mailinglist

I'm new to C++ / C++11 - What would be a good working alternative? I just need to launch a thread that gives me a future, whom get()-method is called later in an boost::asio async loop.

Upvotes: 5

Views: 849

Answers (3)

Jonathan Wakely
Jonathan Wakely

Reputation: 171303

It is a bug in GCC 4.6 (actually a defect in the C++11 standard) which I've already fixed in 4.7.

As a workaround you can use std::async

Query query;
std::future<SearchResults> ftr = std::async([](Query& q) ->SearchResults {
      index::core::Merger merger;
      return merger.search(q);
    }, query);

This works OK with GCC 4.6, and is simpler and safer that creating a packaged_task and running it in a detached thread anyway.

Upvotes: 3

R. Martinho Fernandes
R. Martinho Fernandes

Reputation: 234504

I don't know if these are the cause of the errors GCC is giving, but they are problematic nonetheless.

[=](Query& q){
        index::core::Merger merger;
        return merger.search(q);
}

Since this lambda doesn't consist of a single return statement, and no explicit return type was given, it has a void return type. I suspect you intended it to return a SearchResults object. And it takes a Query& parameter, so the appropriate signature for the packaged task would be SearchResults(Query&).

[=](Query& q) -> SearchResults {
        index::core::Merger merger;
        return merger.search(q);
}

Upvotes: 1

Dave S
Dave S

Reputation: 21113

The updated code has two problems:

1) The lambda doesn't state it's return type correctly. The syntax you want is (assuming you don't need to copy any local variables) is :

[](Query& q) -> SearchResults {
        index::core::Merger merger;
        return merger.search(q);
}

2) Given that the packaged task requires a Query&, then you will need to pass a reference to a non-constant Query as the second argument to the std::thread constructor, so that it can be passed to the task.

What I can't recall is if you can legally pass a non-constant Query reference properly as the second argument to std::thread, or if you will need to use std::ref(q) so that it properly passes the second argument by reference.

As written, it's attempting to call the task with no arguments, as indicated by

/usr/include/c++/4.6/future:1272:7: note: candidate expects 1 argument, 0 provided

Upvotes: 0

Related Questions