I have the function which type the same as minimal argument:
#include <iostream>
template<typename A, typename B>
auto Min(A a, B b) -> decltype(a < b ? a : b)
{
return a < b ? a : b;
}
int main()
{
auto b = Min(5, 2.0f); // float
auto a = Min(5, 6.0f); // also float ?!
std::cout << typeid(a).name() << std::endl;
std::cout << typeid(b).name() << std::endl;
std::cin.get();
}
But actuale I've got float for a and b. And my console print looks like: float float
Why the second function return type evaluating also as float ?
CodePudding user response:
The conditional operator (?:
) can only yield a single type. In your case, int
and float
share the common type float
, so that is the type the expression will yield.
If you don't want that, you'll need to move your code from being executed at run time and move it into being executed at compile time. Doing that allows you to return different types depending on the conditions at compile time. That would give you a min
function like:
template<auto a, auto b> auto min()
{
if constexpr(a < b)
return a;
else
return b;
}
In the above code, if the if constexpr
is false, the whole return a;
is discarded and the entire body of the function become return b;
and if it is true, the opposite happens and your left with just return a;
. This allows the function to return the type and value of the minimum object.
making this change to your code will give you
#include <iostream>
template<auto a, auto b> auto min()
{
if constexpr(a < b)
return a;
else
return b;
}
int main()
{
auto b = min<5, 2.0f>(); // float
auto a = min<5, 6.0f>(); // int
std::cout << typeid(a).name() << std::endl;
std::cout << typeid(b).name() << std::endl;
std::cin.get();
}
which ouputs
i
f
as seen in this live example