Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I avoid a virtual call when I know the type?

Consider the following code snippet:

struct Base { virtual void func() { } };
struct Derived1 : Base { void func() override { print("1"); } };
struct Derived2 : Base { void func() override { print("2"); } };

class Manager {
    std::vector<std::unique_ptr<Base>> items;

    public:
        template<class T> void add() { items.emplace_back(new T); }
        void funcAll() { for(auto& i : items) i->func(); }
};

int main() {
    Manager m;
    m.add<Derived1>();
    m.add<Derived2>();
    m.funcAll(); // prints "1" and "2"
};

I'm using virtual dispatch in order to call the correct override method from a std::vector of polymorphic objects.

However, I know what type the polymorphic objects are, since I specify that in Manager::add<T>.

My idea was to avoid a virtual call by taking the address of the member function T::func() and directly storing it somewhere. However that's impossible, since I would need to store it as void* and cast it back in Manager::funcAll(), but I do not have type information at that moment.

My question is: it seems that in this situation I have more information than usual for polymorphism (the user specifies the derived type T in Manager::add<T>) - is there any way I can use this type information to prevent a seemingly unneeded virtual call? (An user should be able to create its own classes that derive from Base in its code, however.)

like image 455
Vittorio Romeo Avatar asked Oct 21 '13 15:10

Vittorio Romeo


1 Answers

However, I know what type the polymorphic objects are, since I specify that in Manager::add<T>.

No you don't. Within add you know the type of the object that's being added; but you can add objects of different types, as you do in your example. There's no way for funcAll to statically determine the types of the elements unless you parametrise Manager to only handle one type.

If you did know the type, then you could call the function non-virtually:

i->T::func();

But, to reiterate, you can't determine the type statically here.

like image 129
Mike Seymour Avatar answered Oct 23 '22 18:10

Mike Seymour