Home > OS >  Use base class implementation when base is template type
Use base class implementation when base is template type

Time:04-08

I have a class that receives its base type as a template arg and I want my derived class to call a function, print. This function should use the derived implementation by default but if the base class has a print function it should use the base implementation.

#include <iostream>

class BaseWithPrint {
  public:
    static void print(int i) { std::cout << "Base::print\n"; }
};

class BaseWithoutPrint {
};

template <typename B>
class Derived : public B {
  public:
    static void print(bool b) { std::cout << "Derived::bool_print\n"; }

    template <typename T>
    static void print(T t) { std::cout << "Derived::print\n"; }
    
    void Foo() {
        print(1);
        print(true);
        print("foo");
    }
};

int main()
{
    Derived<BaseWithPrint> d1;
    d1.Foo();
    
    
    Derived<BaseWithoutPrint> d2;
    d2.Foo();

    return 0;
}

This code only ever calls the Derived version of print.

Code can be seen at

https://onlinegdb.com/N2IKgp0FY

CodePudding user response:

If you know that the base class will have some kind of print, then you can add using B::print to your derived class. If a perfect match isn't found in the derived, then it'll check the base.

Demo

To handle it for the case where there may be a base print, I think you need to resort to SFINAE. The best SFINAE approach is really going to depend on your real world situation. Here's how I solved your example problem:

template <class T, class = void>
struct if_no_print_add_an_unusable_one : T {
    // only ever called if derived calls with no args and neither
    // the derived class nor the parent classes had that print.
    // ie. Maybe best to force a compile fail:
    void print(); 
};

template <class T>
struct if_no_print_add_an_unusable_one <T, decltype(T().print(int()))> : T {};

//====================================================================


template <class B>
class Derived : public if_no_print_add_an_unusable_one<B> {

    using Parent = if_no_print_add_an_unusable_one<B>;
    using Parent::print;

public:

    // ... same as before
};

Demo

  • Related