开发者

Move objects from unordered associative container

开发者 https://www.devze.com 2023-03-09 20:25 出处:网络
Is there any way in c++0x of moving objects out from unordered associative containers? I need to merge two separate unordered sets and I would like, in case rvalues are involved, to \'recycle\' items

Is there any way in c++0x of moving objects out from unordered associative containers? I need to merge two separate unordered sets and I would like, in case rvalues are involved, to 'recycle' items in the soon-ceased-to-be sets.

Thing is, unordered_set's iterators provide only const references to the stored items. I had thought initially of using const_cast to throw away the const-ness, but upon further reading it seems this results in undefined behavior. Any suggestion?

EDIT

Take this simple-minded example:

#include <string>
#include <unordered_set>

using namespace std;

void merge_sets(unordered_set<string> &s1, unordered_set<string> &&s2)
{
   // Something like this, which (of course) does not work.开发者_如何学JAVA
   for (auto it = s2.begin(); it != s2.end(); ++it) {
     s1.insert(std::move(*it));
   }
}

int main()
{
   unordered_set<string> s1, s2;
   // Fill first set:
   s1.insert("hello");
   s1.insert("world");
   // Fill second set.
   s2.insert("foo");
   merge_sets(s1,std::move(s2));
   // After this operation, s2 is empty and s1 contains "hello", "world" and "foo".
}

In other words, I would like to be able to move the items from s2 instead of copying them. There should be a way to "extract" items from a set in such a way that the item is copied/moved and then erased from the current set.


There is no such functionality in the current spec. But you are not alone in requesting it. It is possible that we may get this functionality in the future, but only if people such as yourself make lots of noise about needing it.

LWG issue 839 has a comment marked "[ 2009-09-19 Howard adds: ]" which describes an API for splicing nodes from one node-based container to another. Using your code it would look like:

void merge_sets(unordered_set<string> &s1, unordered_set<string> &&s2)
{
   // Something like this, which (of course) does not work.
   for (auto it = s2.begin(); it != s2.end();) {
     s1.insert(s2.remove(it++));
   }
}

This would not involve any memory allocation or deallocation. It would not even require moving or copying from your element. It literally passes a node from one unordered_set<string> to another.

Tell your National Body representative that you need this functionality. Tell comp.std.c++ you need this functionality. If you're not sure this API meets your needs, ask me, either privately or here, and I will clarify if I can.


Why not merge the two sets by using one of them as the target, rather than merging them into a third, separate set? This would at least let you avoid copying elements from one of the source sets (presumably you'd choose the larger one).

Or, if the elements are large, you should store them indirectly using smart pointers (e.g. boost::shared_ptr<>), in which case it will be easy to copy the pointers from the two sources to the target and never copy an actual object.


You cannot change an element in a Set (ordered or not) because this breaks the uniqueness guarantee.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号