我正在使用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!!!
}
}
答案 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;
}
}
使用std::set
执行此操作既错误又不可能。
一个坏主意,因为std::set
是一个基于节点的容器,它努力维护排序顺序。我们不需要节点。我们不需要排序顺序。所以我们使用的是比我们需要的更强大的容器。
不可能,因为std::set
的内容是设计不可变的。
不可能,因为std::future
不提供operator<
,也没有一个合理的位置来挂钩用户提供的比较功能。
请注意,shared_future
具有const
get()
方法,因此可以以不可变的方式存储它们。但它们仍然没有为用户提供的订购操作提供“挂钩”。