Reputation: 215
Just can't understand what's going on. Is there anyone who can explain these clearly? If so, please give me some clues or keywords to search.
template <typename T1, typename T2>
auto max (T1 a, T2 b) {
std::cout << "1" << std::endl;
return a > b ? a : b;
}
template <typename RT, typename T1, typename T2>
RT max (T1 a, T2 b) {
std::cout << "2" << std::endl;
return a > b ? a : b;
}
void func() {
auto a = max(4, 7.2); // 1 ?
auto b = max<long double>(7.2, 4); // 2 ?
auto c = max<int>(3.4, 2); // 2 ?
auto e = max<double, int>(3.4, 2); // 1 ?
}
If 2nd max function is not defined, every max call works just fine. On what ground 2nd max is called. What's the rule for it?
Upvotes: 2
Views: 64
Reputation: 5613
If you don't specify a template type, the second form is never used, because RT cannot be deduced, and must be specified.
If you do specify a type, and it is different to T1 deduced from the argument then the second form is used.
Note that the first form is actually C++14, not C++11. In C++11 you have to specify the return type one way or another.
The second form is C++11, and might be provided in C++14 for backward compatibility. Also in principle the second form lets you control the widening, but in practice I'm not sure what the second form gets you, as ?: has to resolve to a single size type. [This answers your supplementary question I think]
For example if the two types were signed and unsigned and the return type was double (but you would get a warning), the ?: result would be probably unsigned (or an error), then cast to double, which is unhelpful. Ideally you need a third version to handle signed/unsigned mismatch anyway, if you care - this is a whole can of special case worms to resolve cleanly.
If it was written long-hand with 2 return statements then it would correctly widen both halves. Better yet, if the casts were performed before the comparison...
Upvotes: 3
Reputation: 16455
max(4, 7.2)
generates a function from first template because two parameters <int, double>
are known.
max<long double>(7.2, 4)
generates a function from second template because three parameters (long double, double, int)
are known.
max<int>(4, 7.2)
is the same as before.
max<double, int>(3.4, 2)
generates a function from first template because the two given template parameters fit to the given values. The two parameters are <double, int>
The compiler tries to deduce the types from function call, if no template parameters are given.
Upvotes: 1