1

To compute the maximum of two values, I have a specialized function and a generic templated version of the same function. During testing, I am passing a char and a double as argument to the function and as there is no function that matches the type of arguments, I am expecting the compiler to throw error. But it is not the case

#include <iostream>
using namespace std;

int max(int a, int b) {
    cout << "resolved to max() specialized\n";
    return a > b ? a : b;
}

template<typename T>
T max(T a, T b) {
    cout << "resolved to max() templated\n";
    return a > b ? a : b;
}

int main() {
    cout << max('a',2.1) << "\n";   // why specialized max(int,int) is invoked ?
    return 0;
}
codeling
  • 11,056
  • 4
  • 42
  • 71
kbh
  • 21
  • 2
  • Does this answer your question? [No Automatic Cast from \`int\` to \`float\` with Template Function](https://stackoverflow.com/questions/32914496/no-automatic-cast-from-int-to-float-with-template-function) – Jean-Baptiste Yunès Apr 07 '22 at 06:51
  • 3
    There's is no specialization, only an *overload*. And that overload is selected because both `'a'` and `2.1` can be implicitly converted to `int`. There's no such implicit conversion possible between `char` and `double`. – Some programmer dude Apr 07 '22 at 06:51
  • Regarding the specialization, if you define the template *first* then define a function like `template<> int max(int, int)` then that's a specialization. – Some programmer dude Apr 07 '22 at 06:52
  • 1
    `std::max` is also defined in the standard library. Since you are using `using namespace std;` the overloads from the standard library may also participate in overload resolution, which will cause you headaches sooner or later. – user17732522 Apr 07 '22 at 07:04
  • Did you want something like [this](https://gcc.godbolt.org/z/x6rT1TqY8)? – Simon Kraemer Apr 07 '22 at 07:15
  • 1
    Regarding the comment by @user17732522, see [Why is "using namespace std;" considered bad practice?](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) – Some programmer dude Apr 07 '22 at 07:15

2 Answers2

4
template<typename T>
T max(T a, T b) {
    cout << "resolved to max() templated\n";
    return a > b ? a : b;
}

Here a and b must be of the same type to match the template definition. As 'a' is char and '2.1' is double this template isn't considered.

On the other hand you a have a function that takes two ints. As char and double are both implicitly convertible to int this "overload" is used.

Simon Kraemer
  • 5,700
  • 1
  • 19
  • 49
1

You don't specialize anything here and the overloaded int max(int a, int b) function is not preferred over the template, but is the only choice. If you remove it, the template is not chosen either.

bogso
  • 11
  • 1
  • Thanks for the quick responses. But when i introduce another function operating on doubles, I get compiler error as call of overloaded max is ambigious. ``` double max(double a, double b) { std::cout << "resolved to max() double\n"; return a > b ? a : b; } ``` – kbh Apr 07 '22 at 08:11
  • as two functions are available for implicit conversion, one to ints and another one to doubles, the compiler is confused as to which one to choose and throwing an error. Can you please confirm my assumption here ? – kbh Apr 07 '22 at 08:36
  • Yes, in such case there are two matching functions and it is not clear, which should be chosen, since the arguments from the function call can be implicitly converted to either of (int,int) and (double,double). However, if you'd add a function overload with argument types of char and double e.g: `int max(char a, double b)`, the new function would be chosen over the other two, the code would compile and run correctly. – bogso Apr 07 '22 at 09:38