C++ workaroud virtual template method

Viewed 390

i know there is nothing like virtual template method in C++, but as it seems it is exactly what i need. Is there any workaround i could use? I am thankful for any suggestion.

I would like to add Entities to a vector by a add method, which need to be virtual and also template, how to avoid this?

#include <iostream>
#include <vector>

class EntityBase {
public:
};

class EntityDerived1 : public EntityBase {
public:
};

class EntityDerived2 : public EntityBase {
public:
};

class ContainerBase {
public:
    template<typename T>
    virtual void add() = 0; // i know this is not allowed!!!
};

class ContainerConcrete : public ContainerBase {
public:
    template<typename T>
    void add() override {   // i know this is not allowed!!!
        data.push_back(std::make_shared<T>());
    }

    void doSecretStuffWithDataHere() {
        //  ...
    }

private:
    std::vector<std::shared_ptr<EntityBase>>    data;
};

class Engine {
public:
    Engine() :
        container(std::make_shared<ContainerConcrete>())
    {}

    ContainerBase& getContainer() {
        auto rawPointer = container.get();
        return *container;
    }

private:
    std::shared_ptr<ContainerConcrete> container;
};

int main() {
    Engine  engine;
    
    ContainerBase& container = engine.getContainer();
    container.add<EntityDerived1>();
    container.add<EntityDerived2>();
}
1 Answers

Just make add a regular virtual function that takes shared_ptr as a parameter

class ContainerBase {
public:
    virtual void add(std::shared_ptr<EntityBase>) = 0;
};

class ContainerConcrete : public ContainerBase {
public:
    void add(std::shared_ptr<EntityBase> p) override {
        data.push_back(p);
    }
    // . . .

And then invoke it with make_shared for the desired type:

int main() {
    Engine  engine;

    ContainerBase& container = engine.getContainer();
    container.add(std::make_shared<EntityDerived1>());
    container.add(std::make_shared<EntityDerived2>());
}

Alternatively you can add a templated overload that invokes make_shared:

    virtual void add(std::shared_ptr<EntityBase>) = 0;
    template<typename T>
    void add() {
        add(std::make_shared<T>());
    }
Related