Connecting Tech Pros Worldwide Forums | Help | Site Map

std::set sorting mechanism

gipsy boy
Guest
 
Posts: n/a
#1: Jul 23 '05
I've got a std::set with a custom comparator.
When I add things, it puts them in the right place.
When I change these objects (and I can tell they are effectively
changed), the set doesn't 'auto-sort' with these changes. How can I do this?
I store pointers in the set, but the comparator compares the contents of
these pointers.

--
- gipsy boy

Victor Bazarov
Guest
 
Posts: n/a
#2: Jul 23 '05

re: std::set sorting mechanism


gipsy boy wrote:[color=blue]
> I've got a std::set with a custom comparator.
> When I add things, it puts them in the right place.
> When I change these objects (and I can tell they are effectively
> changed), the set doesn't 'auto-sort' with these changes. How can I do
> this?
> I store pointers in the set, but the comparator compares the contents of
> these pointers.[/color]

There is no auto-resort option for std::set or a member function that
would force the set to resort itself. That's the whole point of the
set is that it has a relatively short insertion and retrieval times.

What's wrong with (remove + reinsert) approach I suggested instead of
changing the value?

BTW, why do you feel you need a set? Are the elements supposed to be
unique? OK, if you have 'a', 'b', 'c' in your set, and then change the
first to be 'c', what happens? The set is not a set any longer, is it?

If you feel that you need the capability to edit elements _after_ they
have been stored, but keep them sorted, you need to rethink which of
the standard containers to use (or maybe just roll your own). You can
use 'multiset', it can store object with the same values and still get
them in and out quickly. You can use 'list' and, say, insertion-sort
it when you add things to it, and when you change things.

Victor
chris
Guest
 
Posts: n/a
#3: Jul 23 '05

re: std::set sorting mechanism


gipsy boy wrote:[color=blue]
> I've got a std::set with a custom comparator.
> When I add things, it puts them in the right place.
> When I change these objects (and I can tell they are effectively
> changed), the set doesn't 'auto-sort' with these changes. How can I do
> this?
> I store pointers in the set, but the comparator compares the contents of
> these pointers.
>[/color]

Unfortunatly sets don't work like that, you shouldn't change the
relative ordering of elements in a set (I can't actually find the bit of
the standard that says that right now. 23.1.2 points 9 and 10 kind of
say it, but I'm not convinced they are worded very well).

If you only want to be able to get to the first element in the the
sorted set, then consider looking at heaps, which are designed for this
kind of thing. Alternatively it's off to a vector and resorting I'm
afraid (or some custom class).

Chris
chris
Guest
 
Posts: n/a
#4: Jul 23 '05

re: std::set sorting mechanism


Victor Bazarov wrote:[color=blue]
> gipsy boy wrote:
>[color=green]
>> I've got a std::set with a custom comparator.
>> When I add things, it puts them in the right place.
>> When I change these objects (and I can tell they are effectively
>> changed), the set doesn't 'auto-sort' with these changes. How can I do
>> this?
>> I store pointers in the set, but the comparator compares the contents
>> of these pointers.[/color]
>
>
> There is no auto-resort option for std::set or a member function that
> would force the set to resort itself. That's the whole point of the
> set is that it has a relatively short insertion and retrieval times.
>
> What's wrong with (remove + reinsert) approach I suggested instead of
> changing the value?
>[/color]
Out of interest, do you agree that changing the values of a set in such
a way that the relative order of elements if changed is actually
forbidden? Is it 23.1.2 points 9 and 10 that say this?

It just worries me, because most implementations of set will not just
not be sorted, but simply not work if you start changing the elements
(in particular they will stop making sure that inserted elements are
unique, and it's possible they might crash). I'm kind of suprised now I
think about it you can get a non-constant iterator to the elements of sets.

Chris
Victor Bazarov
Guest
 
Posts: n/a
#5: Jul 23 '05

re: std::set sorting mechanism


chris wrote:[color=blue]
> Victor Bazarov wrote:
>[color=green]
>> gipsy boy wrote:
>>[color=darkred]
>>> I've got a std::set with a custom comparator.
>>> When I add things, it puts them in the right place.
>>> When I change these objects (and I can tell they are effectively
>>> changed), the set doesn't 'auto-sort' with these changes. How can I
>>> do this?
>>> I store pointers in the set, but the comparator compares the contents
>>> of these pointers.[/color]
>>
>>
>>
>> There is no auto-resort option for std::set or a member function that
>> would force the set to resort itself. That's the whole point of the
>> set is that it has a relatively short insertion and retrieval times.
>>
>> What's wrong with (remove + reinsert) approach I suggested instead of
>> changing the value?
>>[/color]
> Out of interest, do you agree that changing the values of a set in such
> a way that the relative order of elements if changed is actually
> forbidden? Is it 23.1.2 points 9 and 10 that say this?[/color]

My take on this is actually more cautious [and I also urge you to post
your question to comp.std.c++ for clarification]. I think that 23.1.2/9
and 23.1.2/10 simply indicate that the process of _iterating_ through
a container must present a particular order of elements. It does not
say that we can't change values of elements.

There is an embedded conflict in the description of iterators of 'set'.
OOH, they can allow changing of the value_type (i.e. the value type can
be a reference to a non-const object). OTOH, doing so may require
invalidating the rest of iterators (and the whole iteration procedure)
so that it has to be restarted and 'begin()' or 'rbegin()' actually
force at least a re-check of the "structural integrity" of the container.

If only the requirements were a bit stronger, for example, to prohibit
the assignment to *i (where 'i' is std::set::iterator), then everything
would probably fall into place and an implementation that defines the
std::set::iterator::value_type to be a reference to non-const would
suddenly become non-conforming.
[color=blue]
> It just worries me, because most implementations of set will not just
> not be sorted, but simply not work if you start changing the elements
> (in particular they will stop making sure that inserted elements are
> unique, and it's possible they might crash). I'm kind of suprised now I
> think about it you can get a non-constant iterator to the elements of sets.[/color]

I think a good discussion in comp.std.c++ is in order, if it didn't happen
already.

Victor
gipsy boy
Guest
 
Posts: n/a
#6: Jul 23 '05

re: std::set sorting mechanism


Victor Bazarov wrote:[color=blue]
> gipsy boy wrote:
>[color=green]
>> I've got a std::set with a custom comparator.
>> When I add things, it puts them in the right place.
>> When I change these objects (and I can tell they are effectively
>> changed), the set doesn't 'auto-sort' with these changes. How can I do
>> this?
>> I store pointers in the set, but the comparator compares the contents
>> of these pointers.[/color]
>
>
> There is no auto-resort option for std::set or a member function that
> would force the set to resort itself. That's the whole point of the
> set is that it has a relatively short insertion and retrieval times.
>
> What's wrong with (remove + reinsert) approach I suggested instead of
> changing the value?
>
> BTW, why do you feel you need a set? Are the elements supposed to be
> unique? OK, if you have 'a', 'b', 'c' in your set, and then change the
> first to be 'c', what happens? The set is not a set any longer, is it?[/color]

Yeah, I agree sets shouldn't auto-sort.
I think I'll still use a set but like you said I'll just remove/insert
each time. All in all it's an assignment and the deadline is in a couple
of hours, I'll keep it in mind, but I'm a bit tired to change my
architecture.
Thanks for all your help with this by the way,

--
- gipsy boy
gipsy boy
Guest
 
Posts: n/a
#7: Jul 23 '05

re: std::set sorting mechanism


Victor Bazarov wrote:
[color=blue]
> If you feel that you need the capability to edit elements _after_ they
> have been stored, but keep them sorted, you need to rethink which of
> the standard containers to use (or maybe just roll your own). You can
> use 'multiset', it can store object with the same values and still get
> them in and out quickly. You can use 'list' and, say, insertion-sort
> it when you add things to it, and when you change things.[/color]

They had to be unique values, and it was nice to provide a comparator.
(adding an object is probably 99:1 times as more likely to happen that
changing one).

Well, what I'm doing now is that, if the objects get changed, I empty
the entire set, and then use an auxiliary vector to put everything back
in. (apparently, erasing and then inserting a pointer didn't work) Why
is that?
std::set<R*,Rcmp> rSet;
.... // (R* rPtr is now in rSet
rPtr->changeMe();
rSet.erase(rPtr);
rSet.insert(rPtr);

The result of this is that, the changed rPtr is back in the set, but
another object has disappeared. I suppose this is what you both said
about not changing the relative order in any way.
So I'll just clear it and then put everything back in. That's the only
solution right?

--
- gipsy boy
Victor Bazarov
Guest
 
Posts: n/a
#8: Jul 23 '05

re: std::set sorting mechanism


gipsy boy wrote:[color=blue]
> Victor Bazarov wrote:
>[color=green]
>> If you feel that you need the capability to edit elements _after_ they
>> have been stored, but keep them sorted, you need to rethink which of
>> the standard containers to use (or maybe just roll your own). You can
>> use 'multiset', it can store object with the same values and still get
>> them in and out quickly. You can use 'list' and, say, insertion-sort
>> it when you add things to it, and when you change things.[/color]
>
>
> They had to be unique values, and it was nice to provide a comparator.
> (adding an object is probably 99:1 times as more likely to happen that
> changing one).
>
> Well, what I'm doing now is that, if the objects get changed, I empty
> the entire set, and then use an auxiliary vector to put everything back
> in. (apparently, erasing and then inserting a pointer didn't work) Why
> is that?
> std::set<R*,Rcmp> rSet;
> ... // (R* rPtr is now in rSet
> rPtr->changeMe();
> rSet.erase(rPtr);
> rSet.insert(rPtr);[/color]

I think you're doing it a bit in the wrong order. You need

rSet.erase(rPtr);
rPtr->changeMe();
rSet.insert(rPtr);
[color=blue]
> The result of this is that, the changed rPtr is back in the set, but
> another object has disappeared. I suppose this is what you both said
> about not changing the relative order in any way.
> So I'll just clear it and then put everything back in. That's the only
> solution right?[/color]

No. See above.

Victor
Joaquín M López Muñoz
Guest
 
Posts: n/a
#9: Jul 23 '05

re: std::set sorting mechanism


I think this issue was addressed in DR #103:

http://std.dkuug.dk/jtc1/sc22/wg21/d...fects.html#103
HTH

Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo

Closed Thread