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));
}
This gives the following error on VS2017:
error C2280: 'std::unique_ptr>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function
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()));
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());
}
}
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
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With