Search code examples
c++inheritancecasting

How to store all subclasses in different sets c++


I want to store objects relative to their type. I have a Status class which is inherited to create different status such as Burn, Stun, etc...

I would like to store statuses in sets with a set for each type (a character can a multiple burn status at once, so I want to get the set storing all the burn statuses but not other statuses).

my solutions so far looks like this

std::map<std::type_index, std::set<Status*>> statuses;

// access all Burn statuses
for (const Burn* b : statuses.find(typeid(Burn))->second) {} // error : E0144 a value of type "Status *" cannot be used to initialize an entity of type "const DamageModifier *"
**

However this is downcasting and the compiler doesn't want it to work.

My questions are as follow:

  • How could I access a set and downcast it to the right type without copying
  • Do you think of any other way to store all statuses of the same subtype together with easy access ?
    • I dont want to store it all in a set and dynamic cast because it starts getting expensive
    • I dont want to declare one set by hand for each new Status subclass.

Edit :

The problem was that I tried to do two things at once from my last code version

  • Switching from std::set<Status*> to std::map<std::typeid, std::set<Status*>> which is OK as long as you cast the result the same as before
  • Trying to implicitly cast a whole set of pointer which is useless and naive, at least in this context

Both answer helped me realise the problem was that I tried to do both at once.


Solution

  • How could I access a set and downcast it to the right type without copying

    You can use static_cast to down cast:

    for (const Status* s : statuses.find(typeid(Burn))->second) {
        auto b = static_cast<const Burn*>(s);
    }
    

    You must be very careful though to not insert pointers to wrong derived classes into wrong set. That will silently pass compilation and break at runtime (if you're lucky).