std :: set <std :: future>是不可能存在的

时间:2017-08-31 04:31:58

标签: c++ multithreading c++11 set future

我正在使用C ++ 11来做一些线程程序 现在我遇到了这样的情况:

我有std::set<std::future<std::string>> results来存储一些线程结果,当然所有这些线程都会返回一个字符串。

然而,当我尝试获取字符串时,我收到如下错误:

  

将xxx作为xxx的'this'参数传递,丢弃限定符

根据this link,我认为这是因为我试图调用属于set元素的非const函数。换句话说,set的元素是std::future<std::string>std::future<std::string>::get()是非const的元素。这就是我收到这样一个错误的原因。

如果我是对的,这是否意味着我永远不会声明std::set<std::future>,因为get始终无法使用?

这是我的代码:

set<future<string>> results;
results.insert(...); // insert some future
for(auto it = results.begin(); it != results.end();)
{
    if (it->wait_for(std::chrono::seconds(0)) == std::future_status::ready)
    {
        string tmp = it->get();  // ERROR!!!
    }
}

1 个答案:

答案 0 :(得分:4)

在考虑使用什么容器时,您应该考虑“我可以使用std::vector吗?”。如果你的答案是否定的,你应该问“不,真的,我可以用std::vector吗?”。

using namespace std::literals;
std::vector<std::future<std::string>> results;
constexpr auto threads = 10;
for (int i = 0; i < threads; ++i) {
  results.push_back( std::async( std::launch::async,
    [i]{
      std::this_thread::sleep_for( std::chrono::milliseconds((threads-i)%(threads/3)) );
      std::stringstream ss;
      ss << "hello world " << i;
      return ss.str();
    }
  ) );
}
for (auto it = results.begin(); it != results.end();) {
  if (it->wait_for( 0s ) == std::future_status::ready) {
    std::string tmp = it->get();
    std::cout << tmp << "\n";
    std::swap( *it, results.back() );  // noop if already at back
    if (std::next(it)==results.end()) it = results.begin(); // do this before pop back
    results.pop_back(); // Or this could invalidate it
    if (results.begin()==results.end()) break; // empty vector has to be caught early, as it is invalidated if vector is now empty
    continue;
  } else {
    ++it;
    if (it == results.end()) it = results.begin();
    continue;
  }     
}

Live example

使用std::set执行此操作既错误又不可能。

一个坏主意,因为std::set是一个基于节点的容器,它努力维护排序顺序。我们不需要节点。我们不需要排序顺序。所以我们使用的是比我们需要的更强大的容器。

不可能,因为std::set的内容是设计不可变的。

不可能,因为std::future不提供operator<,也没有一个合理的位置来挂钩用户提供的比较功能。

请注意,shared_future具有const get()方法,因此可以以不可变的方式存储它们。但它们仍然没有为用户提供的订购操作提供“挂钩”。