F. Joe
F. Joe

Reputation: 13

Data mismatch and compiler cannot deduce template argument

I have this template function for max

template <typename T>
T max(T a, T b) { return (a > b) ? a : b; }  

And I wanted to replace these:

int max(int a, int b){ return (a > b) ? a : b; }
char cmax(char a, char b){ return (a > b) ? a : b; }  
unsigned int umax(unsigned int a, unsigned int b){ return (a > b) ? a : b; }  

I need a and b to have the same type.
But my code (which I am porting from C to C++) has things like this:

size_t myvar;
...
...
int i = max(myvar,5);  

VS2015 output:

Error   C2672   'max': no matching overloaded function found    
Error   C2672   'max': no matching overloaded function found
Error   C2782   'T max(T,T)': template parameter 'T' is ambiguous
Error   C2784   'T max(T,T)': could not deduce template argument for 'T' from 'int'

Okay, I should probably cast 5 to size_t.

My question is the following: why C allows this? And more importantly, what happens under the hood? Does the compiler casts 5 to size_t or what? What can be the consequences of this?

Thanks :)

Upvotes: 1

Views: 61

Answers (1)

Brian Bi
Brian Bi

Reputation: 119144

In the C code where you're calling max, both arguments are implicitly converted to type int, since the function's parameters have type int. So myvar is converted to int (it is not 5 that is converted to size_t). The conversion from size_t to int should be avoided since it is often narrowing (size_t is often longer than int).

In C++14, you can write a max template that can take two arguments of different types as follows:

template <class T, class U>
auto max(T a, U b) {
    return (a > b) ? a : b;
}

In C++11, the solution is slightly more verbose:

template <class T, class U>
typename std::common_type<T, U>::type max(T a, U b) {
    return (a > b) ? a : b;
}

The return type will be whatever type the ternary expression has. For two integer types of different sizes, the longer type will be chosen, so no information will be lost. (Some information may be lost if one type is signed and the other is unsigned and both have the same length.)

Upvotes: 2

Related Questions