Search code examples
c++templatesinheritancesfinaeoverload-resolution

overloading function and inheritance


I am trying to overload some template function to perform specific action if I call it using a given class MyClass or any derived class MyClassDer. Here is the code:

#include <iostream>

struct MyClass {
    virtual void debug () const {
        std::cerr << "MyClass" << std::endl;
    };
};

struct MyClassDer : public MyClass {
    virtual void debug () const {
        std::cerr << "MyClassDer" << std::endl;
    };
};

template <typename T> void  func  (const T& t) {
    std::cerr << "func template" << std::endl;
}

void func (const MyClass& myClass) {
    std::cerr << "func overloaded" << std::endl;
    myClass.debug ();
}


int main(int argc, char **argv) {
    func (1);
    MyClass myClass;
    func (myClass);
    MyClassDer myClassDer;
    func (myClassDer);
}

The output is:

func template
func overloaded
MyClass
func template

func (myClassDer) calls the template function instead of void func (const MyClass& myClass). What can I do to get the expected behavior?

Thanks


Solution

  • You can use SFINAE:

    #include <type_traits>
    
    template <typename T>
    void func (const T& t, typename std::enable_if<!std::is_base_of<MyClass, T>::value>::type * = nullptr) {
        std::cout << "func template" << std::endl;
    }
    
    template <
        typename T
        , typename = typename std::enable_if<std::is_base_of<MyClass, T>::value>::type
    >
    void func (const T& t) {
        std::cout << "func overloaded" << std::endl;
        t.debug ();
    }
    

    If you don't have C++11, boost provides the same functionality.

    Live example

    EDIT

    This should work without C++11 (using boost):

    #include "boost/type_traits.hpp"
    
    template <typename T>
    void func (const T& t, typename boost::enable_if<!boost::is_base_of<MyClass, T>::value>::type * = 0) {
        std::cout << "func template" << std::endl;
    }
    
    template <typename T>
    void func (const T& t, typename boost::enable_if<boost::is_base_of<MyClass, T>::value>::type * = 0) {
        std::cout << "func overloaded" << std::endl;
        t.debug ();
    }