Modify STL multiset

M

Mike Copeland

With a lot of help from various people here, I have gotten my project
started (thanks!). However, I have reached another roadblock: modifying
the stored objects' data values.
I don't with to change any of the "key" values, but I need to update
counts and flags changes. When I had this structure defined as an STL
map, I could use "find" and modify the data, but I can't see how to do
so with a multiset.
Near the end of this code I try to use "find" with an existing key,
but although it compiles, it doesn't work. Please advise. TIA

#pragma warning (disable:4786)
#include <set>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <string>
using namespace std;
//----------------------------------------------------------------------
class TeamData
{
public:
string id; // Team Code (TId4)
string TeamName; // Team's Name
bool Added; // Added to working stack of teams
char TypeCode; // Team type Code
int ctm1; // Count of Team Members-1
int ctm2; // Count of Team Members-2
bool operator<(TeamData const &inObj) const
{
return id < inObj.id ? true : inObj.id < id ? false :
TeamName < inObj.TeamName ? true : false;
}
};

ostream &operator<<(ostream &inStream, TeamData const &inData)
{
return inStream << setw(4) << inData.id << " "
<< setw(30) << inData.TeamName << " "
<< setw(1) << inData.TypeCode << endl;
}

typedef multiset<TeamData> TeamMasterSet;
typedef TeamMasterSet::iterator TeamMasterIter;

struct CIterComp_m2
{
bool operator()(TeamMasterIter const &in1, TeamMasterIter const
&in2) const
{
return ((*in1).TeamName) < ((*in2).TeamName) ? true :
((*in2).TeamName) < ((*in1).TeamName) ? false :
*in1 < *in2;
}
};

struct CIterComp_m3
{
bool operator()(TeamMasterIter const &in1, TeamMasterIter const
&in2) const
{
return ((*in1).TypeCode) < ((*in2).TypeCode) ? true :
((*in2).TypeCode) < ((*in1).TypeCode) ? false :
*in1 < *in2;
}
};

typedef multiset<TeamMasterIter, CIterComp_m2> CSlaveSet2;
typedef multiset<TeamMasterIter, CIterComp_m3> CSlaveSet3;
//////////////////////////////////////////////////////////
int main()
{
TeamMasterSet masterSet;
CSlaveSet2 slaveSet2;
CSlaveSet3 slaveSet3;
TeamData data;
data.ctm1 = data.ctm2 = 0, data.Added = true;
data.id = "1001", data.TeamName = "QUEST", data.TypeCode = 'C';
TeamMasterIter iter = masterSet.insert(data);
slaveSet2.insert(iter), slaveSet3.insert(iter);
data.id = "1002", data.TeamName = "RUNNERS", data.TypeCode = 'B';
iter = masterSet.insert(data), slaveSet2.insert(iter),
slaveSet3.insert(iter);
data.id = "7000", data.TeamName = "QUEST CLUB", data.TypeCode = 'C';
iter = iter = masterSet.insert(data), slaveSet2.insert(iter),
slaveSet3.insert(iter);
data.id = "B321", data.TeamName = "BEAT JABBA", data.TypeCode = 'G';
iter = masterSet.insert(data), slaveSet2.insert(iter),
slaveSet3.insert(iter);
data.id = "C162", data.TeamName = "COBRA KAI", data.TypeCode = 'M';
iter = masterSet.insert(data), slaveSet2.insert(iter),
slaveSet3.insert(iter);
// DEFAULT ORDERING
for(TeamMasterIter iter1 = masterSet.begin(); iter1 != masterSet.end
(); ++iter1)
cout << *iter1;
cout << string(20, '-') << endl;
///////////////////////////////////////////////////////////////////////
data.id = "1002", iter1 = masterSet.find(data); // doesn't work...
if(iter1 != masterSet.end())
{
data = *iter1; // if we get here, how do I change/update data?
}
///////////////////////////////////////////////////////////////////////
// SECOND ORDERING
for(CSlaveSet2::iterator iter2 = slaveSet2.begin(); iter2 !=
slaveSet2.end(); ++iter2)
cout << **iter2;
cout << string(20, '-') << endl;
// THIRD ORDERING
for(CSlaveSet3::iterator iter3 = slaveSet3.begin(); iter3 !=
slaveSet3.end(); ++iter3)
cout << **iter3;

return 0;
}
 
F

Francesco

Hi.  I adress this issue in my article here:

http://i42.co.uk/stuff/mutable_set.htm

It includes downloadable header file(s) that you are free to use/modify.

/Leigh

Adding to what Mr. Johnston has written you have two more options,
IMHO:
- copy the data, remove it from the sets, change the copy, reinsert it
in the sets
- instead of storing the data itself in the master set, you could
store in each set a pointer to the data (possibly allocate on the
heap). This allows you to freely change anything (breaking also the
"contract" with the sets, obviously) without const_casting. If you're
developing a full fledged GUI application this might make sense
anyway.

For the other problem, you have to use lower_bound and upper_bound.
Like this:

TeamData dummy; // start with a "clean" object

dummy.id = "1002";
TeamMasterSet loIter = masterSet.lower_bound( dummy );
TeamMasterSet hiIter = masterSet.upper_bound( dummy );


now loIter will point to the "lowest" spot in the set where you could
insert a new team with id 1002
hiIter will point to "highest" spot where you could insert a new team
with id 1002
in other words if there is any team with id 1002 it will be between
loIter and hiIter
if there is no team with that id loIter and hiIter will be the same.

Hope it helps,
Francesco
 
R

red floyd

   With a lot of help from various people here, I have gotten my project
started (thanks!).  However, I have reached another roadblock: modifying
the stored objects' data values.  
   I don't with to change any of the "key" values, but I need to update
counts and flags changes.  When I had this structure defined as an STL
map, I could use "find" and modify the data, but I can't see how to do
so with a multiset.  
   Near the end of this code I try to use "find" with an existing key,
but although it compiles, it doesn't work.  Please advise.  TIA

Use a std::multimap instead of a multiset.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,522
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top