Map to store 3 items

B

Brad

New to C++. Just ran into a need to store three things in a map. Before
trying it, I thought I'd post here and ask for advice. Here is an
example of what I need to store:

map<string name, string prefix, int length>

Both name and prefix would be unique for each map entry. I was wondering
if the the first entry could be an array that holds the two items (name
and prefix), but then I wondered how an iterator would behave when
it->first is called.

Any suggestions or pointers on using a map with three items would be
much appreciated.

Brad
 
J

Jerry Coffin

New to C++. Just ran into a need to store three things in a map. Before
trying it, I thought I'd post here and ask for advice. Here is an
example of what I need to store:

map<string name, string prefix, int length>

Both name and prefix would be unique for each map entry. I was wondering
if the the first entry could be an array that holds the two items (name
and prefix), but then I wondered how an iterator would behave when
it->first is called.

It can't be an array -- it has to be copyable and assignable. It can be
a pair<string, string> though, in which case you'd do something like
it->first.first or it->first.second, to access the name and prefix
respectively.

Of course, you could also create a class of your own to hold the two
strings, something like:

class key {
string name;
string prefix;
public:
key(string n, string p) : name(n), prefix(p) {}
key(key const &other) : name(other.name), prefix(other.prefix) {}
key &operator=(key const &other) {
name = other.name;
prefix = other.prefix;
return *this;
}

bool operator<(key const &other) const {
if (name < other.name)
return true;
if (name > other.name)
return false;
if (prefix < other.prefix)
return true;
return false;
}
};
 
D

David Côme

New to C++. Just ran into a need to store three things in a map. Before
trying it, I thought I'd post here and ask for advice. Here is an
example of what I need to store:

map<string name, string prefix, int length>

Both name and prefix would be unique for each map entry. I was wondering
if the the first entry could be an array that holds the two items (name
and prefix), but then I wondered how an iterator would behave when
it->first is called.

Any suggestions or pointers on using a map with three items would be
much appreciated.

Brad


Boost Tuple ?
 
J

Juha Nieminen

Jerry said:
class key {
string name;
string prefix;
public:
key(string n, string p) : name(n), prefix(p) {}
key(key const &other) : name(other.name), prefix(other.prefix) {}
key &operator=(key const &other) {
name = other.name;
prefix = other.prefix;
return *this;
}

What exactly do you need that copy constructor and assignment operator
for? They are doing exactly what the default ones would do. They are
useless.

How about simply:

struct Key
{
std::string name, prefix;

Key(std::string& n = "", std::string p = ""): name(n), prefix(p) {}

bool operator<(const Key& rhs)
{
return name == rhs.name ? prefix < rhs.prefix : name < rhs.name;
}
}
 
J

Jerry Coffin

[ ... ]
What exactly do you need that copy constructor and assignment operator
for? They are doing exactly what the default ones would do. They are
useless.

You're right -- I should have pointed out that I was including them only
for emphasis, but they're only doing what the compiler would generate if
they weren't included.
 
J

James Kanze

It's not clear what constitutes your map key and what is in your map
value. In general, both can be structs or classes. If you use a struct
or class as the map key you have to define operator<() for it, otherwise
the map could not maintain the keys in sorted order.

That's not really true, and in fact, most of the time, if I'm
using a class type as a key, I'll specify the ordering function
for the map, rather than define an operator< which might have an
otherwise counter-intuitive meaning. Of course, if there is a
logical ordering, which makes sense in general, and isn't being
"invented" just in order to use the objects in map, then
defining operator< is the simpler solution.
struct MyKeyType {
std::string name_;
std::string prefix_;
MyKeyType(const std::string& name, const std::string& prefix)
: name_(name), prefix_(prefix)
{}
bool operator<(const MyKeyType& b) const {
return name_<b.name_ || (name_==b.name_ && prefix_<b.prefix_);
}
};
std::map<MyKeyType, int> my_map;
my_map[MyKeyType("foo","bar")] = 22;
std::string prefix1 = my_map.begin()->first.prefix_;
The same can be accomplished by using std::pair, but then you
cannot give meaningful names to the struct members, and
combining more data to the key becomes cumbersome.

Agreed. std::pair is almost never a good solution.
 

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

Members online

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top