0

Question is the code. It looks like the 2nd function is more special than the 1st one. Why the more general one is called in the following code? How can I make the other function to be used?

template <typename T>
class Base{
public:
    Base(){}
    void print() const {cout<<"Base class"<<endl;}
};

template <typename T>
class Derived :public Base<T>{
public:
    Derived() {}
    void print() const {cout<<"Derived class"<<endl;}
};

template <typename T>
void func(T x){    // <----- Why is function is called?
    x.print();
    cout<<"in func(T)"<<endl;
}

template <typename T>
void func(const Base<T>& x){
    x.print();
    cout<<"in func(Base<T>)"<<endl;
}

int main () {
    Base<int> b;
    Derived<int> d;
    func(d);
    return 0;
}

Note that I am passing the Derived object to the function.

Tim
  • 355
  • 1
  • 8
  • This post can help you: http://stackoverflow.com/questions/22411482/c-template-functions-overload-resolution. See the answer of @NikosAthanasiou. – chema989 Jun 22 '16 at 02:32
  • 1
    Possible duplicate of: http://stackoverflow.com/questions/31563580/c-templated-function-overloading-rules?lq=1 – sameerkn Jun 22 '16 at 06:51

2 Answers2

0

Note that I am passing the Derived object to the function.

In this case, there must be one implicit conversion (from Derived<T> to Base<T>) for the argument of the 2nd function template. While for the 1st function template it's an exact match and preferred.

How can I make the other function to be used?

You can change the parameter type of the 2nd function template to avoid implicit conversion. You can also use std::enable_if with std::is_base_of to make it only work with the base class and its derived classes.

template <typename T, template <typename> class D>
typename std::enable_if<std::is_base_of<Base<T>, D<T>>::value>::type
func(const D<T>& x){
    x.print();
    cout<<"in func(Base<T>)"<<endl;
}

Live Demo


BTW: I think Base::print() should be a virtual function.

skypjack
  • 49,335
  • 19
  • 95
  • 187
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
0

Simple answer would be:

  • template instantiation are done at compile time: At compile time there is no function which can take Derived<int>, therefore void func(T x) is used to instantiate the definition of that kind of function.

implicit dynamic conversion are done at run time.

sameerkn
  • 2,209
  • 1
  • 12
  • 13