Why is less than the operator accepting different types of parameters, and std :: min not?

#include <iostream> int main(){ int a = 1; long long b = 2; std::cout<<(a<b); std::cout<<std::min(a, b); return 0; } 

 > In file included from /usr/include/c++/4.8/bits/char_traits.h:39:0, > from /usr/include/c++/4.8/ios:40, > from /usr/include/c++/4.8/ostream:38, > from /usr/include/c++/4.8/iostream:39, > from sum_to.cpp:1: /usr/include/c++/4.8/bits/stl_algobase.h:239:5: note: template<class > _Tp, class _Compare> const _Tp& std::min(const _Tp&, const _Tp&, _Compare) > min(const _Tp& __a, const _Tp& __b, _Compare __comp) > ^ /usr/include/c++/4.8/bits/stl_algobase.h:239:5: note: template argument deduction/substitution failed: sum_to.cpp:7:29: > note: deduced conflicting types for parameter 'const _Tp' ('int' and > 'long long int') > std::cout<<std::min(a, b); --- 

Thanks to chris, the comment in the message about the function overloading The calculation of the template argument does not take into account conversions. One template parameter cannot match two types

So std::min not working.

Why < will work?

+8
c ++ overloading templates
source share
5 answers

Since the built-in < applies numerical promotions , and the output of the template argument does not work.

+7
source share

As explained in other answers, the reason is that std::min requires the argument types to be identical if deduction is to be performed, whereas < implies the usual arithmetic conversions (Β§5.9 / 2), which will make sure that the types are converted to "common denominator". Please note that Β§13.6 / 12 lists the built-in operators as candidates:

For each pair of advanced arithmetic types L and R there is a candidate operator operator of the form

 // […] LR operator<(L , R ); // […] 

where LR is the result of ordinary arithmetic conversions between types L and R


Actually, std::min must deal with various types. Below is a more modern approach:

 template <typename T> constexpr decltype(auto) min(T&& t) {return std::forward<T>(t);} template <typename T, typename U, typename... Args> constexpr auto min(T&& t, U&&u, Args&&... args) { std::common_type_t<T, U> const& _t(std::forward<T>(t)), _u(std::forward<U>(u)); return min(_t<_u? _t : _u, std::forward<Args>(args)...); } 

Demo

+3
source share

This is because std::min is a template function.

 template <class T> const T& min (const T& a, const T& b) { return !(b<a)?a:b; // or: return !comp(b,a)?a:b; for version (2) } 

therefore, you must have the same type for the arguments, but if you use (a<b) , then a can be implicitly converted to long long

+2
source share

Primitive types do not overload operators, so ordinary arithmetic conversions are applied and your int is converted to long long, and "<" has a real value.

You can't even overload operators for primitive types: https://isocpp.org/wiki/faq/intrinsic-types#intrinsics-and-operator-overloading

Example showing your int progressing to long

 // common_type example #include <iostream> #include <type_traits> int main() { typedef std::common_type<int, long long>::type A; // i std::cout << "A: " << std::is_same<long long,A>::value << std::endl; return 0; } 

Documentation http://en.cppreference.com/w/cpp/language/operator_arithmetic

For binary operators (except shifts), if the advanced operands are of different types, an additional set of implicit conversions are applied, known as regular arithmetic conversions with the goal of generating a generic type (also available through the std :: common_type trait type)

-one
source share

The < operator is binary, so the compiler can convert the arguments to the same type and compare them.

Otherwise, the min function must return something. How could the compiler guess which type it should return?

-one
source share

All Articles