【问题标题】:std::packaged_task compile error w/ gcc 4.6带有 gcc 4.6 的 std::packaged_task 编译错误
【发布时间】:2012-06-11 18:33:04
【问题描述】:

我正在尝试使用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:再次更新代码以修复错误并包含完整的错误消息。

g++-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 的新手 - 有什么好的替代方案?我只需要启动一个给我未来的线程,稍后在boost::asio 异步循环中调用get()-method。

【问题讨论】:

  • 一个问题是您已将 packaged_task 声明为不带参数并返回 SearchResults,但 lambda 只带一个参数。我希望你的声明是std::packaged_task&lt;SearchResults(Query&amp;)&gt;
  • 你真的可以发布完整的错误信息吗?看来你只发布了一半。这让人难以理解。
  • 我已更改代码以反映缺少的参数,并使用更新的代码添加了完整的错误消息。还有很多问题。

标签: c++ concurrency c++11 g++ std


【解决方案1】:

这是 GCC 4.6 中的一个错误(实际上是 C++11 标准中的 defect),我已经在 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 并在分离的线程中运行它更简单、更安全。

【讨论】:

    【解决方案2】:

    我不知道这些是否是 GCC 给出的错误的原因,但它们仍然存在问题。

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

    由于这个 lambda 不包含单个 return 语句,并且没有给出明确的返回类型,所以它有一个 void 返回类型。我怀疑你打算让它返回一个 SearchResults 对象。它需要一个Query&amp; 参数,因此打包任务的适当签名将是SearchResults(Query&amp;)

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

    【讨论】:

    • 感谢您的回答,我现在尝试将其更改为:std::packaged_task&lt;SearchResults(Query&amp;)&gt; task([SearchResults] (Query&amp; q){ index::core::Merger merger; return merger.search(q); });
    • @emteh 哦,对不起。这不是正确的语法。我编辑了它。我出去做其他事情,忘记在答案中写正确的语法......
    • 谢谢,解决了。与此相关的错误消失了。我仍然有原始错误消息。 [=][] 没有区别。
    【解决方案3】:

    更新后的代码有两个问题:

    1) lambda 没有正确说明它的返回类型。您想要的语法是(假设您不需要复制任何局部变量)是:

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

    2) 鉴于打包的任务需要Query&amp;,那么您需要将非常量查询的引用作为第二个参数传递给std::thread 构造函数,以便可以将其传递给任务.

    我想不起来的是,您是否可以合法地将非常量查询引用作为第二个参数正确传递给std::thread,或者您是否需要使用std::ref(q) 以便它正确传递第二个参数参考。

    正如所写,它正在尝试不带参数调用任务,如

    所示

    /usr/include/c++/4.6/future:1272:7: 注意:候选人需要 1 个参数,提供 0 个

    【讨论】:

    • std::thread 默认会复制参数,所以你需要std::ref
    • @davs:谢谢现在修复它,解决了一些问题。原来的错误仍然存​​在,通过。
    • @JonathanWakely:谢谢,std::ref(query) 没有区别。还是有std::bind相关的错误。
    猜你喜欢
    • 1970-01-01
    • 2017-06-27
    • 2016-11-13
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多