Search code examples
c++templatesinheritancemember

How to refer derived class in template member?


The code below won't compile:

struct Base
{
    std::vector<void(Base::*)(void)> x;
};

struct Derived : public Base
{
    void foo() {}
};

// ...

Derived d;
d.x.push_back(&Derived::foo);

Is it possible to refer derived class in template member x? In the example above I specify exactly Base and derived classes cannot push their own member functions into vector x.


Solution

  • Casting is bad since your code have to assume that this will be called only for instance of Derived class. This means that you either have to assume that all items in x are instance of Derived (in such case declaration of x is to general and should be changed to std::vector<void(Derived::*)(void)> x;) or you have to maintain extra information what which class method is stored in specific position of x. Both approaches are bad.

    In modern C++ it is much better do do it like this:

    struct Base
    {
        std::vector<std::function<void()>> x;
    };
    
    struct Derived : public Base
    {
        void foo() {}
    };
    
    // ...
    
    Derived d;
    d.x.push_back([&d](){ d.foo(); });
    

    Another good approach can be CRTP:

    template<class T>
    struct Base
    {
        std::vector<void(T::*)(void)> x;
    };
    
    struct Derived : public Base<Derived>
    {
        void foo() {}
    };
    
    // ...
    
    Derived d;
    d.x.push_back(&Derived::foo);