从std :: set提取仅移动类型 [英] Extracting move only type from std::set
问题描述
我有一个std::set<std::unique_ptr<T>>
,我想将其移动到std::vector<std::unique_ptr<T>>
I have a std::set<std::unique_ptr<T>>
and I'd like to move it to a std::vector<std::unique_ptr<T>>
#include <set>
#include <vector>
#include <memory>
class C {};
int main()
{
std::set<std::unique_ptr<const C>> s;
std::vector<std::unique_ptr<const C>> v;
std::move(s.begin(), s.end(), std::back_inserter(v));
}
这在VS2017上出现以下错误:
This gives the following error on VS2017:
错误C2280:'std :: unique_ptr> :: unique_ptr(const std :: unique_ptr< _Ty,std :: default_delete< _Ty >>&)':试图引用已删除的函数
error C2280: 'std::unique_ptr>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function
我们不能将迭代器从std::set
移至非常量变量吗?有什么办法可以解决这个问题?
Can't we make move iterators to non-const variables from a std::set
? What could be a viable solution to this problem?
推荐答案
In order to extract move-only elements from a set, the only possibility is to use the extract
method, which was added in C++17:
while (!s.empty())
v.emplace_back(std::move(s.extract(s.begin()).value()));
如果您不能使用C ++ 17,则仅当您确保其在所施加的顺序中保持相同的位置时,才允许修改集合的元素(例如,使用mutable
). -也就是说,只要与集合中的所有其他成员相比,它在您的比较器下具有相同的结果.为此,您可以提供一个比较器,该比较器在非空之前对空的唯一指针进行排序(请注意,标准不保证这样做),并在修改后立即擦除修改后的元素:
If you cannot use C++17, it is permissible to modify an element of a set (e.g. using mutable
) only if you ensure that it retains the same position in the imposed ordering - that is, as long as it has the same result under your comparator when compared to all other members of the set. You can do this by providing a comparator that orders empty unique pointers before non-empty (note that the standard does not guarantee this) and erasing the modified element immediately after modifying it:
template<class T> struct MutableWrapper { mutable T value; };
template<class T> struct MutableWrapperCompare {
bool operator()(MutableWrapper<T> const& lhs, MutableWrapper<T> const& rhs) {
return lhs.value && rhs.value ? lhs.value < rhs.value : rhs.value;
}
};
int main()
{
std::set<MutableWrapper<std::unique_ptr<const C>>, MutableWrapperCompare<std::unique_ptr<const C>>> s;
std::vector<std::unique_ptr<const C>> v;
while (!s.empty())
{
v.emplace_back(std::move(s.begin()->value));
s.erase(s.begin());
}
}
然而,这是非常丑陋和危险的;您最好使用 Boost.Container ,它具有C ++ 17提取方法(自1.62.0起 ;它没有记录,但这只是一个疏忽,请注意相应的extract
方法记录在map
和multimap
中.)
This is however rather ugly and dangerous; you would be better off using boost::container::set
from Boost.Container, which has the C++17 extract method (since 1.62.0; it was undocumented, but this is just an oversight, note the corresponding extract
methods are documented for map
and multimap
).
这篇关于从std :: set提取仅移动类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!