Search code examples
c++templatesmetaprogrammingvariadic-templatesc++20

Multiple inheritance with templated template


I want to do multiple inheritance via template arguments and pass reference to this in each base class, so I can call top level object's method from each base class's method. I can do it with manual inheritance, but I want to be able to do this via templates arguments.

Godbolt link

Godbolt link with manual inheritance

#include <cstdio>

template <typename T>
struct Foo {
    Foo(T &t)
        : t_(t) {

    }

    void foo() {
        t_.call("foo");
    }

    T &t_;
};

template <typename T>
struct Bar {
    Bar(T &t)
        : t_(t) {

    }

    void bar() {
        t_.call("bar");
    }

    T &t_;
};

template <template<typename> typename... Methods>
struct Impl : public Methods<Impl>... {
    Impl() 
        : Methods<Impl>(*this)... {

    }

    void call(const char *m) {
        printf(m);
    }
};

int main() {
    auto t = Impl<Foo, Bar>();

    t.foo();
    t.bar();
}

I tried this approach, but it gives type/value mismatch at argument 1 in template parameter list for 'template<class> class ... Methods'


Solution

  • Thanks to @Nicol Bolas, he advised to use static_cast and CRTP for this

    #include <cstdio>
    
    template <typename T>
    struct Foo {
        void foo() {
            static_cast<T*>(this)->call("foo");
        }
    };
    
    template <typename T>
    struct Bar {
        void bar() {
            static_cast<T*>(this)->call("bar");
        }
    };
    
    template <template<typename> typename... Methods>
    struct Impl : public Methods<Impl<Methods...>>... {
        Impl() {
    
        }
    
        void call(const char *m) {
            printf(m);
        }
    };
    
    int main() {
        auto t = Impl<Foo, Bar>();
    
        t.foo();
        t.bar();
    }