There's no point in using
auto in your program.
Consider this (
incorrect) function template instead:
1 2 3 4 5
|
template <typename T, typename U>
T get_max(T a, U b)
{
return a > b? a: b;
}
|
The problem lies in the fact that while the function's return type is
T, the type of the expression
a > b? a: b
depends instead on the types of
a and
b, according to complicated rules. For example, if
T is
int and
U is
long long, then the type of
a > b? a: b is
long long.
As such,
get_max(1000, std::numeric_limits<long long>:::max()) will convert
a > b? a: b from
long long to
int, which throws away information:
https://godbolt.org/z/YqYjxq
To solve the problem, we need a way to ensure the return type is appropriate for the types involved. Before C++14, we have to write the return type ourselves. It's not a reasonable solution. Here's how it looks, just for kicks:
1 2 3 4 5 6 7 8
|
template <typename T, typename U>
typename std::remove_reference<
decltype(std::declval<T&>() > std::declval<U&>()?
std::declval<T&>(): std::declval<U&>())>::type
get_max(T a, U b)
{
return a > b? a: b;
}
|
This is
totally absurd for the problem it solves.
More simply, we can use trailing return types (which exist for this purpose)
1 2 3 4 5 6
|
template <typename T, typename U>
auto get_max(T a, U b) ->
typename std::remove_reference<decltype(a > b? a: b)>::type
{
return a > b? a: b;
}
|
But happily we don't need to bother with this, because, since C++14, we can allow the compiler to figure out the appropriate type on its own:
1 2 3 4 5
|
template <typename T, typename U>
auto get_max(T a, U b)
{
return a > b? a: b;
}
|