Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Passing other types to std::set::erase().

Reply
Thread Tools

Passing other types to std::set::erase().

 
 
JC
Guest
Posts: n/a
 
      06-24-2009
I have a class where each instance has a unique ID associated with it,
like this (I use "..." to mean "other things", not a variable
parameter list):

typedef ... ID;

class Data {
public:
Data (ID id, ...);
bool operator < (const Data &d) const throw () { return id_ <
d.id_; }
...
private:
ID id_;
...
};

Instances are equivalent if their IDs are equivalent. I am storing
these in an std::set<Data>. I'd like to be able to erase elements from
the set given only an ID, that is:

std::set<Data> somedata = ...;
ID id = ...;
somedata.erase(id);

I've found two ways to make this work, neither are ideal for reasons I
don't want to get in to:

1) Provide an implicit Data(ID) constructor to construct dummy Data
instances used for ID comparisons.

2) Use an std::map<ID,Data> instead.

Is there a way I can erase elements from the set by ID without
constructing dummy Data instances, and without using some other
container type instead?

Thanks!
Jason
 
Reply With Quote
 
 
 
 
joseph cook
Guest
Posts: n/a
 
      06-24-2009
On Jun 23, 10:09*pm, JC <(E-Mail Removed)> wrote:
> I have a class where each instance has a unique ID associated with it,
> like this <snip>
> Instances are equivalent if their IDs are equivalent.


If the IDs are unique, no two will ever be equivalant, but...

> I am storing
> these in an std::set<Data>. I'd like to be able to erase elements from
> the set given only an ID, that is:
>
> std::set<Data> somedata = ...;
> ID id = ...;
> somedata.erase(id);
>
> I've found two ways to make this work, neither are ideal for reasons I
> don't want to get in to:
>
> * 1) Provide an implicit Data(ID) constructor to construct dummy Data
> instances used for ID comparisons.


Ack. Don't do that.

> Is there a way I can erase elements from the set by ID without
> constructing dummy Data instances, and without using some other
> container type instead?


If you define operator==(ID&), then you can accomplish your goal.
Given your description, these seems like it would provide appropriate
semantics as well.

hth,
Joe C
 
Reply With Quote
 
 
 
 
jasonc
Guest
Posts: n/a
 
      06-24-2009
On Jun 23, 10:36*pm, joseph cook <(E-Mail Removed)> wrote:
> On Jun 23, 10:09*pm, JC <(E-Mail Removed)> wrote:
>
> > I have a class where each instance has a unique ID associated with it,
> > like this <snip>
> > Instances are equivalent if their IDs are equivalent.

[snip]
> > I am storing
> > these in an std::set<Data>. I'd like to be able to erase elements from
> > the set given only an ID, that is:

>
> > std::set<Data> somedata = ...;
> > ID id = ...;
> > somedata.erase(id);

>
> > Is there a way I can erase elements from the set by ID without
> > constructing dummy Data instances, and without using some other
> > container type instead?

>
> If you define operator==(ID&), then you can accomplish your goal.
> Given your description, these seems like it would provide appropriate
> semantics as well.



Thanks for your reply. An == operator makes sense in general; however,
this still doesn't solve the problem, as std::set<Data>::erase(const
Data&) takes a Data parameter, not an ID parameter, so compilation
would still fail with an error along the lines of "no match for
somedata.erase(ID)".

Also, AFAIK, doesn't set always use operator< for comparisons rather
than operator== (operator<(ID&) doesn't solve the problem either)?

Jason
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      06-24-2009
* JC:
> I have a class where each instance has a unique ID associated with it,
> like this (I use "..." to mean "other things", not a variable
> parameter list):
>
> typedef ... ID;
>
> class Data {
> public:
> Data (ID id, ...);
> bool operator < (const Data &d) const throw () { return id_ <
> d.id_; }
> ...
> private:
> ID id_;
> ...
> };
>
> Instances are equivalent if their IDs are equivalent. I am storing
> these in an std::set<Data>. I'd like to be able to erase elements from
> the set given only an ID, that is:
>
> std::set<Data> somedata = ...;
> ID id = ...;
> somedata.erase(id);
>
> I've found two ways to make this work, neither are ideal for reasons I
> don't want to get in to:
>
> 1) Provide an implicit Data(ID) constructor to construct dummy Data
> instances used for ID comparisons.
>
> 2) Use an std::map<ID,Data> instead.
>
> Is there a way I can erase elements from the set by ID without
> constructing dummy Data instances, and without using some other
> container type instead?


The map idea is the closest. The "reasons I don't want to get in to" are
important in order to provide more specific advice. However, keep in mind that
the general solution to any Computer Science problem is ... indirection (you may
have to use two collections, one to capture your idea of id->instance
association and another to capture the allocation/lifetime aspect).


Cheers & hth.,

- Alf

--
Due to hosting requirements I need visits to <url: http://alfps.izfree.com/>.
No ads, and there is some C++ stuff! Just going there is good. Linking
to it is even better! Thanks in advance!
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      06-24-2009
On Jun 24, 4:51 am, jasonc <(E-Mail Removed)> wrote:
> On Jun 23, 10:36 pm, joseph cook <(E-Mail Removed)> wrote:
> > On Jun 23, 10:09 pm, JC <(E-Mail Removed)> wrote:


> > > I have a class where each instance has a unique ID
> > > associated with it, like this <snip>
> > > Instances are equivalent if their IDs are equivalent.

> [snip]
> > > I am storing these in an std::set<Data>. I'd like to be
> > > able to erase elements from the set given only an ID, that
> > > is:


> > > std::set<Data> somedata = ...;
> > > ID id = ...;
> > > somedata.erase(id);


> > > Is there a way I can erase elements from the set by ID
> > > without constructing dummy Data instances, and without
> > > using some other container type instead?


> > If you define operator==(ID&), then you can accomplish your
> > goal. Given your description, these seems like it would
> > provide appropriate semantics as well.


> Thanks for your reply. An == operator makes sense in general;
> however, this still doesn't solve the problem, as
> std::set<Data>::erase(const Data&) takes a Data parameter, not
> an ID parameter, so compilation would still fail with an error
> along the lines of "no match for somedata.erase(ID)".


> Also, AFAIK, doesn't set always use operator< for comparisons
> rather than operator== (operator<(ID&) doesn't solve the
> problem either)?


You're right on both counts.

In the end, your problem comes down to getting the set to find
the element, given just the idea. This is exactly what std::map
was designed for---if you need to find an element using an
object of a different type as key, you should be using std::map,
and not std::set.

If you're not doing a lot of insertions, you might also consider
using a sorted std::vector, and std::lower_bound---this function
does allow for a "key" with a different type.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
JC2
Guest
Posts: n/a
 
      07-02-2009
On Jun 24, 4:02*am, James Kanze <(E-Mail Removed)> wrote:
> On Jun 24, 4:51 am, jasonc <(E-Mail Removed)> wrote:
>
>
>
> > On Jun 23, 10:36 pm, joseph cook <(E-Mail Removed)> wrote:
> > > On Jun 23, 10:09 pm, JC <(E-Mail Removed)> wrote:
> > > > I have a class where each instance has a unique ID
> > > > associated with it, like this <snip>
> > > > Instances are equivalent if their IDs are equivalent.

> > [snip]
> > > > I am storing these in an std::set<Data>. I'd like to be
> > > > able to erase elements from the set given only an ID, that
> > > > is:
> > > > std::set<Data> somedata = ...;
> > > > ID id = ...;
> > > > somedata.erase(id);
> > > > Is there a way I can erase elements from the set by ID
> > > > without constructing dummy Data instances, and without
> > > > using some other container type instead?
> > > If you define operator==(ID&), then you can accomplish your
> > > goal. *Given your description, these seems like it would
> > > provide appropriate semantics as well.

> > Thanks for your reply. An == operator makes sense in general;
> > however, this still doesn't solve the problem, as
> > std::set<Data>::erase(const Data&) takes a Data parameter, not
> > an ID parameter, so compilation would still fail with an error
> > along the lines of "no match for somedata.erase(ID)".
> > Also, AFAIK, doesn't set always use operator< for comparisons
> > rather than operator== (operator<(ID&) doesn't solve the
> > problem either)?

>
> You're right on both counts.
>
> In the end, your problem comes down to getting the set to find
> the element, given just the idea. *This is exactly what std::map
> was designed for---if you need to find an element using an
> object of a different type as key, you should be using std::map,
> and not std::set.
>
> If you're not doing a lot of insertions, you might also consider
> using a sorted std::vector, and std::lower_bound---this function
> does allow for a "key" with a different type.


Thanks; I forgot about this project for a few days.

I ended up having to settle for an std::map. I don't particularly like
the redundancy of storing the ID both in the map and in the object
itself (it opens the possibility of inconsistent entries in the map
where the key doesn't match the actual ID), however I ended up going
with this as the solution and hiding it behind some container class so
consistency in the map would always be guaranteed. This seems to be
working well, so I guess the problem is solved.

Thanks!
JC
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Can XSD simple types be derived from complex types? Soren Kuula XML 2 12-01-2005 07:51 PM
Where are ref types that are members of value types stored? Sathyaish ASP .Net 2 05-22-2005 07:32 PM
missing types in module types? Manlio Perillo Python 0 05-29-2004 06:33 AM
Boost + Python C/API: Mixing python return types with boost return types Steve Knight Python 2 10-10-2003 10:11 AM
STD types vs C++ intrinsic types Jeremy Cowles C++ 5 08-19-2003 05:33 PM



Advertisments