When I write
T min(T& a,T& b)
{return a<b?a:b;}
and call min(3,4)
, it will yield a error.
How can I implement a generic min?
That's because non-const
lvalue references (T&
) cannot bind to rvalues (3
and 4
are rvalues, which intuitively means that they do not have an object identity).
Try using lvalue references to const
instead, which can bind to rvalues (after all, the min()
function is not supposed to alter the state of its arguments).
Besides, do not forget the template<typename T>
part if you are writing a function template:
template<typename T> // <== Don't forget this, if you are writing a template
T min(T const& a, T const& b)
// ^^^^^ ^^^^^
{
return (a < b) ? a : b;
}
For instance, consider this small program:
#include <iostream>
template<typename T> // <== Don't forget this, if you are writing a template
T min(T const& a, T const& b)
// ^^^^^ ^^^^^
{
return (a < b) ? a : b;
}
int main()
{
int x = 42;
int y = 1729;
std::cout << min(x, y) << std::endl; // Passing lvalues, that would be OK also
// with your original code.
std::cout << min(42, 1729) << std::endl; // Passing rvalues, this would not be OK
// with your original code (non-const
// lvalue references cannot bind to rvalues)
}
Here is a live example.
UPDATE:
The above solution only allows passing values of the same type to min()
, otherwise the compiler won't be able to perform type deduction (if the first and second argument have different types, what should T
be?):
min(3.14, 42); // Huh? What is `T` here, `double` or `int`?
To force the compiler to use a specific type for T
, you can specify the template argument explicitly:
min<double>(3.14, 42);
However, this is not a very elegant choice (the user has to type the correct template argument manually every time). Rather, you could let your function template accept two template type parameters instead of one:
#include <type_traits>
template<typename T, typename U>
typename std::common_type<T, U>::type min(T const& a, U const& b)
{
return (a < b) ? a : b;
}
And use the std::common_type<>
type trait (available since C++11) to figure out the right type to be used as the return type.
Once again, here is a live example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With