samedi 2 janvier 2016

Loop vector of unique_ptrs and call correct overload polymorphically

I have a vector of unique_ptrs to objects that share a common base class. I would like to iterate through the vector and call the correct overload of a function, based on the stored type. The problem is that this function is not a member of the class (for those of you who enjoy talking design patterns: imagine I'm implementing a visitor class and f is the Visit method). Consider the following code example (or try it online):

#include <iostream>
#include <memory>
#include <vector>
using namespace std;

class Base{};
class A : public Base {};
class B : public Base {};
class C : public Base {};

void f(Base* b) { cout << "Calling Base :(\n"; }
void f(A* a) { cout << "It is an A!\n"; }
void f(B* b) { cout << "It is a B\n"; }
void f(C* c) { cout << "It is a C!\n"; }

template<class Derived>
void push(vector<unique_ptr<Base>>& v, Derived* obj)
{
    v.push_back(std::unique_ptr<Derived>{obj});
}

int main() {
    vector<unique_ptr<Base>> v{};
    push(v, new A{});
    push(v, new B{});
    push(v, new C{});

    for(auto& obj : v)
    {
        f(obj.get());
    }

    return 0;
}

There are superficial differences with my code (f is a class method instead of a free function, I don't use using namespace std) but this shows the general idea. I see

Calling Base :(
Calling Base :(
Calling Base :(

whereas I would like to see

It is an A!
It is a B!
It is a C!

I would like to know if I can get the correct overload of f to be called (I would like to get rid of the f(Base*) version altogether) without resorting to manual typechecking using dynamic_cast and such?

Thanks!

Aucun commentaire:

Enregistrer un commentaire