4

The code is taken from Partial template function specialization with enable_if: make default implementation . I was expecting the call to dummy(5) to be ambiguous between the "Generic" and the "Integral" overloads as T is deduced as int in both cases. The second parameter resolves to void in both cases. Aren't they equally "ranked" in the call to dummy(5) ? How does the compiler choose the "Generic" version ?

#include <iostream>

template<typename T, typename Enable = void>
void dummy(T t)
{
  std::cout << "Generic: " << t << std::endl;
}


template<typename T, typename std::enable_if<std::is_integral<T>::value>::type>
void dummy(T t)
{
  std::cout << "Integral: " << t << std::endl;
}


template<typename T, typename std::enable_if<std::is_floating_point<T>::value>::type>
void dummy(T t)
{
  std::cout << "Floating point: " << t << std::endl;
}

int main() {
  dummy(5); // Print "Generic: 5"
  dummy(5.); // Print "Generic: 5"
}

sdp
  • 97
  • 1
  • 4

1 Answers1

4

The "Integral" overload can't be called because the 2nd template argument can't be inferred. (Note that typename std::enable_if<std::is_integral<T>::value>::type is trying to decalre a non-type template parameter with type void when T is integer type, which is invalid.)

If you change the type to pointer (as non-type template parameter) and provide a default argument for it (like the "Generic" overload, which is declaring type template parameter with default argument void) then the calling would be ambiguous.

template<typename T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
void dummy(T t)
{
  std::cout << "Integral: " << t << std::endl;
}
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • 1
    @sdp They're not the same. `typename Enable = void` is declaring a type template parameter with default argument `void`. `typename std::enable_if::value>::type` is trying to decalre a non-type template parameter with type `void` when `T` is integer type, which is invalid. – songyuanyao Jul 24 '21 at 07:10
  • @sdp Try to remove the "Generic" overload, you'll see the "Integral" overload won't be called at all. – songyuanyao Jul 24 '21 at 07:10