33

I need to key some data in a map by a type. Currently I have something like this:

struct TypeInfoComparer
{
  bool operator()(std::type_info const* a, std::type_info const* b) const
  {
    return a->before(*b);
  };
};

std::map<std::type_info const*, Foo, TypeInfoComparer> d_fooByTypeId;

Which I can then look up from using (for example, in a template method having <typename T>:

auto pair = d_fooByTypeId.find(&typeid(T));

However today I was reading about std::type_index which seems to be intended for use in such a case as this.

I'm interested in improving my C++ knowledge. Can someone please explain whether I should modify my code to use std::type_index, and why? Is there a reason beyond being able to remove the TypeInfoComparer?

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
  • 1
    Why do you think the `type_info` returned by `typeid` is persistant and unique for a given type? – Yakk - Adam Nevraumont Nov 16 '13 at 22:04
  • 7
    @Yakk: "The result of a typeid expression is an lvalue of static type const std::type_info... The lifetime of the object referred to by the lvalue extends to the end of the program." ([expr.typeid]). He doesn't assume that it's unique; he's using the standard `before` member function in his comparator. I don't know why everyone misses that fact. – rici Nov 16 '13 at 22:08

2 Answers2

30

type_index is "a simple wrapper for type_info which can be used as an index type in associative containers (23.4) and in unordered associative containers (23.5)". If you use type_index instead of type_info*, you will free yourself from having to provide an explicit comparator in your maps. The only cost is that you need to #include <typeindex>.

Another benefit is that it will allow you to switch to (or also use) hashmaps (aka unordered_maps).

On the whole, since it simplifies your code, I'd say "go for it".

rici
  • 234,347
  • 28
  • 237
  • 341
  • 2
    and there is little reason to use a `map` as the `before` order is arbitrary. – Yakk - Adam Nevraumont Nov 17 '13 at 02:10
  • What would be the difference between using std::type_index vs using std::type_info::hash_code()? Or I mean a size_t. – Zebrafish Mar 29 '21 at 00:33
  • @zebrafish: `std::type_index` is a total ordering over types in which two different types are guaranteed to produce different values with a consistent order; it can be used for either ordered or unordered containers. `std::type_info::hash_code()` may return the same value for two different types, so it can only be used as a hash function. In practice, there probably isn't a difference. But that would be an implementation detail. – rici Mar 29 '21 at 01:32
6

I don't think using a pointer to the result returned from typeid(x) is guaranteed to always yield the same result. In particular it seems problematic to guarantee the same object to be returned when shared libraries are used. The intended use of std::type_info for sorting is to use before() member. The class std::type_index wraps this into a simoler interface.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • *"I don't think using a pointer to the result returned from typeid(x) is guaranteed to always yield the same result"*... Well, it is guaranteed, by the spec, to return the *same* object everytime you use `typeid(x)`. – Nawaz Jan 22 '18 at 19:40
  • 3
    @Nawaz "There is no guarantee that the same std::type_info instance will be referred to by all evaluations of the typeid expression on the same type [...]" https://en.cppreference.com/w/cpp/language/typeid under "notes" – phön Aug 08 '18 at 11:47
  • 1
    @phön: You're right and my previous comment turned out to be wrong. However, I'm keeping my previous (incorrect) comment intact so that others dont make the same mistake. – Nawaz Aug 08 '18 at 14:09