Why is the compiler choosing this template function over an overloaded non-template function?

后端 未结 2 751
一生所求
一生所求 2021-01-11 20:45

Using VC++ 2010, given the following:

class Base { };
class Derived : public Base { };

template void foo(T& t);  // A
void foo(Base&          


        
相关标签:
2条回答
  • 2021-01-11 21:13

    The template version is being selected because it is a better match when called with an argument of type Derived than the overloaded version. You can use SFINAE to drop the template version from overload resolution so that the other version is selected when calling with arguments of type Base or Derived.

    #include <type_traits>
    #include <iostream>
    
    class Base { };
    class Derived : public Base { };
    
    template<class T> 
    typename std::enable_if<
      std::is_base_of<Base, T>::value == false
    >::type
    foo(T&)  
    { 
      std::cout << "template foo" << std::endl; 
    }
    
    
    void foo(Base&)
    { 
      std::cout << "non-template foo" << std::endl; 
    }
    
    
    int main()
    {
      Derived d;
      Base b;
    
      foo( d );
      foo( b );
    }
    
    0 讨论(0)
  • 2021-01-11 21:25

    All things being equal, nontemplate functions are preferred over function templates. However, in your scenario, all things are not equal: (A) is an exact match with T = Derived, but (B) requires a derived-to-base conversion of the argument.

    You can work around this for specific cases (like this one) by using SFINAE (substitution failure is not an error) to prevent (A) from being instantiated with a type that is derived from Base:

    #include <type_traits>
    #include <utility>
    
    template <typename T>
    typename std::enable_if<
        !std::is_base_of<Base, T>::value
    >::type foo(T& x)
    {
    }
    
    void foo(Base& x)
    {
    }
    
    0 讨论(0)
提交回复
热议问题