Use template with map

Started by
3 comments, last by Zakwayda 13 years, 12 months ago
Hi, I was wondering if it was possible to use a template for the second value of map? For example:

template <typename T>
std::map<char*, T*> m_Map;
Because when I try to compile the code, it says that the "Microsoft C/C++ Optimizer Compiler has stopped working". So I've looked on google but haven't found much information. I read that I had to had the keyword "typename" in front of the map declaration, but it still doesn't work. Is it possible at all to create such a map? My problem is that I am storing objects by key and I want to return the objects (which are all children of a mother class) but I can't get the children class, it only returns me the base class.
Advertisement
No, that's not possible. Storing a pointer to the base class is the correct approach, and from there you'd either use dynamic dispatch -- which in C++ is virtual functions -- or down-casting, but the latter should generally be avoided. It might also make the most sense to store object instances directly, but that's something you'd have to decide on for yourself.

Something else I noticed is that you're using char* as a map key, which in almost all cases is incorrect and won't behave the way you expect. If the key is a string, the C++ library has its own string type called std::string that you should use instead.
Quote:Original post by Zipster
Something else I noticed is that you're using char* as a map key, which in almost all cases is incorrect and won't behave the way you expect. If the key is a string, the C++ library has its own string type called std::string that you should use instead.

Sorry for being offtopic.

It should also be mentioned that using strings as keys in an std::map is highly inefficient, because in the worst case, a lookup operation will require O(log n) expensive string comparison operations.

You should either try to find a different type for your keys or use a hash map (such as std::unordered_map, if TR1 is available, or boost::unordered_map).

If your strings are constant, then using const char* is still wrong, because according to the C++ standard, it is not guaranteed that pointers to different string constants are different!

If you have to use strings, and your strings are immutable, you can use Boost.Flyweight. However, this requires special care when using DLLs, and even then it still has its quirks.

So the bottom line is, either don't use strings, or use a hash map.
Quote:Original post by majickthise
It should also be mentioned that using strings as keys in an std::map is highly inefficient, because in the worst case, a lookup operation will require O(log n) expensive string comparison operations.

You should either try to find a different type for your keys or use a hash map (such as std::unordered_map, if TR1 is available, or boost::unordered_map).

I disagree, or at least, I don't necessarily agree. This is a premature optimization. String comparisons are slow, but that might not matter in the OP's situation. Remember the 80-20 rule and make sure your string comparisons are actually a bottleneck before you "optimize" them away.
Quote:Original post by majickthise
Quote:Original post by Zipster
Something else I noticed is that you're using char* as a map key, which in almost all cases is incorrect and won't behave the way you expect. If the key is a string, the C++ library has its own string type called std::string that you should use instead.

Sorry for being offtopic.

It should also be mentioned that using strings as keys in an std::map is highly inefficient, because in the worst case, a lookup operation will require O(log n) expensive string comparison operations.

You should either try to find a different type for your keys or use a hash map (such as std::unordered_map, if TR1 is available, or boost::unordered_map).

If your strings are constant, then using const char* is still wrong, because according to the C++ standard, it is not guaranteed that pointers to different string constants are different!

If you have to use strings, and your strings are immutable, you can use Boost.Flyweight. However, this requires special care when using DLLs, and even then it still has its quirks.

So the bottom line is, either don't use strings, or use a hash map.
Yeah, that sounds a little premature to me. We don't even know what the OP will be using this for. It could be for resource acquisition or some other situation where queries are made infrequently and/or only at times when performance isn't critical. Or, N could be relatively small, meaning that even if key comparison has a non-trivial cost associated with it, the overall cost of each search will probably still be low.

In any case, I wouldn't just assume that using std::string as the key type will be 'highly inefficient'.

This topic is closed to new replies.

Advertisement