2012-06-07 2 views
5

Я пытаюсь запустить функцию в потоке с помощью std::packaged_taskстанд :: packaged_task ошибка компиляции ж/НКУ 4,6

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: Обновлен код еще раз, чтобы исправить ошибки и включить полное сообщение об ошибке.

г ++ - 4,6 (на Ubuntu 10.04) не может скомпилировать код:

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 

Я читал, что это может быть из-за ошибки: gcc-mailinglist

Я новичок в C++/C++ 11 - Что было бы хорошей рабочей альтернативой? Мне просто нужно запустить поток, который дает мне будущее, которое get() -method вызывается позже в асинхронном цикле boost::asio.

+0

Одна из проблем заключается в том, что вы объявили packaged_task как не принимать аргументы и возвращать SearchResults, но lambda принимает один аргумент. Я бы ожидал, что ваша декларация будет 'std :: packaged_task ' –

+0

Можете ли вы опубликовать полное сообщение об ошибке? Кажется, вы разместили только половину. Это делает его непонятным. –

+0

Я изменил код, чтобы отразить отсутствующий аргумент, и добавил полное сообщение об ошибке с обновленным кодом. Все еще проблема. –

ответ

3

Это ошибка в GCC 4.6 (фактически defect в стандарте C++ 11), который я уже зафиксировал в 4.7.

В качестве временного решения можно использовать std::async

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

Это хорошо работает с GCC 4.6, и проще и безопаснее, что создание packaged_task и запустить его в отдельном потоке в любом случае.

+0

Спасибо! Это работает! –

1

Я не знаю, являются ли они причиной ошибок, которые GCC дает, но тем не менее они проблематичны.

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

Поскольку лямбда не состоит из одного оператора возврата, а не явного возвращаемого типа был дан, он имеет тип void возврата. Я подозреваю, что вы намеревались вернуть объект SearchResults. И он принимает параметр Query&, поэтому соответствующая подпись для упакованной задачи будет SearchResults(Query&).

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

Спасибо за ваш ответ, я попытался изменить его сейчас: 'станд :: packaged_task задачи ([SearchResults] (Query & Q) { индекс :: основной :: Слияния слияния; return merger.search (q); }); ' –

+0

@emteh О, простите об этом. Это не правильный синтаксис. Я отредактировал его. Я вышел сделать что-то еще и забыл написать правильный синтаксис в ответе ... –

+0

Спасибо, исправлено. Ошибки, связанные с этим, исчезли. У меня все еще есть сообщение об ошибке orignal. '[=]' Vs. '[]' не имеет значения. –

0

Обновленный код имеет две проблемы:

1) лямбда не указывает, что это тип возвращаемого правильно. Синтаксис Вы хотите это (при условии, что вам не нужно копировать любые локальные переменные) является:

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

2) Учитывая, что упаковано задача требует Query&, то вам нужно будет передать ссылку на не- constant Запрос в качестве второго аргумента для конструктора std::thread, чтобы он мог быть передан задаче.

То, что я не могу вспомнить, заключается в том, что вы можете законно передать непостоянную ссылку на запрос должным образом в качестве второго аргумента в std::thread, или если вам нужно будет использовать std::ref(q), чтобы он надлежащим образом передал второй аргумент по ссылке.

Как написано, он пытается вызвать задачу без аргументов, как указано

/usr/include/c++/4.6/future:1272:7: примечание: кандидат ожидает 1 аргумент, 0 при условии,

+0

'std :: thread' будет копировать аргументы по умолчанию, поэтому вам нужно' std :: ref' –

+0

@ davs: Спасибо, исправлено это сейчас, что позволило решить некоторые проблемы. Исходная ошибка все еще существует. –

+0

@JonathanWakely: Спасибо, 'std :: ref (query)' не имеет никакого значения. Все еще есть ошибка 'std :: bind'. –

Смежные вопросы