Pins
Pins

Reputation: 217

How to avoid dynamic cast in polymorphism with derived class of template type

I have this architecture(in short version):

class BaseBatch {
    virtual ~BaseBatch(){};
};

template<class T>
class Batch : public BaseBatch
{

    void draw(T* data) {
       do something..
    }
};

class BatchManager
{
private:
   static std::vector<BaseBatch*> batches;
public:

    template <class T>
    static void placeData(T* data){

        //Loop through the entire container
        bool found = false;
        for (auto&& b: batches())
            if (b->get_type() == typeid(T)) {

                dynamic_cast<Batch<T>*>(b)->draw(data);
                found = true;
            }

        //If no bach found, create a new One
        if (not found) {
            batches.push_back(new Batch<T>);
        }
    }
};

Problem is that the placeData function is called multiple (many) times per 1 loop and I think that the dynamic casting is a real pain for the performance but cannot figure out how can I solve this without using it. Is it really that problematic or I shouldn´t bother with it and keep using it? If i should avoid it, what would you suggest? Thanks

Upvotes: 0

Views: 697

Answers (1)

David
David

Reputation: 28178

Instead of using std::vector<Batch*> use a std::unordered_map<std::type_index, std::unique_ptr<BaseBatch>>. To access a batch use batches.find(std::type_index(typeid(T))), then static_cast it to a Batch<T>*. static_cast has no runtime overhead. To create a new batch, use std::type_index(typeid(T)) as the key.

The performance of dynamic_cast likely isn't the issue here. In fact, with this solution calling typeid is likely just as bad as dynamic_cast. The real potential gain is the lookup speed of the unordered_map vs iterating through every element of a who-knows-how-big vector and trying a dynamic_cast.

Upvotes: 1

Related Questions