tags:

views:

132

answers:

5

I need a key in the map, however, I found it should be multiple data. Can I put these data in one user defined class and put the whole class as a key in the map?

Will it impact the time efficiency?

What other concerns should be applied here?

+2  A: 

As long as that class has an operator< (or otherwise make its instances <-comparable, e.g. by defining a free-standing operator< that can accept two such instances as arguments one way or another -- or, again, you make the map with an explicit comparison object), it will work fine. It will be fast if and only if that operator or function (and other crucial bits like its copy constructor) are, of course.

Edit: added the extra bit that operator< (if that's what you want to use rather than providing an explicit comparison object) need not be an operator, but could be a separate function -- tx to @Neil for pointing this out in a comment.

Alex Martelli
There is no need for the class to have an operator < - it must simply be less-than comparable. This could be implemented via a free function.
anon
@Neil, excellent point -- editing to fix, tx.
Alex Martelli
std::map<T, U> uses std::less<T>. You can also specialize that.
MSalters
+1  A: 

Yes, you can use any class as the key as long as it implements the less-than operator< or you give a comparison trait in the map definition.

Don't worry about the time unless it proves to be a problem in practice.

Mark Ransom
+1  A: 

Regarding using user defined classes for keys, sure. Because of the way Map is defined, your must define a 'less than' operator (operator<) for your class, or give a comparator object when constructing the map. Here's an example of the latter.

Regarding efficiency, don't worry prematurely, but one concern is how costly it is to make copies of the key object.

This is not about efficiency, but avoid altering the content of the keys in way that would affect the result of operator< while they're in the map.

If you're interested in efficient indexing with the different components of the key (since you say it is 'multiple data', look at boost::multi_index.

dimatura
+3  A: 

Any type can be used as a key as long as it is

  • Copyable
  • Assignable
  • Comparable, since the map is sorted by key

If your class is just a simple structure, then it's already copyable and assignable. For a class to be comparable, you must either implement operator<, or create the map with a custom comparison function to use instead.

The only impact on time efficiency comes from larger objects taking longer to copy and compare. If the objects need to be that size, then there's nothing you can do about that, so don't worry about it.

Mike Seymour
You could also specialize `std::less` for the type.
sbi
+1  A: 

A type to be used as a map's key type either needs to have a std::less<T> specialization or another predicate (instead of the default std::less) passed to the map. The default implementation of std::less uses <. So you can

  1. overload operator<() for your type
  2. specialize std::less for it
  3. pass different predicate to std::map.
sbi