简体   繁体   中英

Why less than operator accepts different types of params while 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 comment in function overloading post Template argument deduction doesn't take conversions into account. One template parameter can't match two types

So std::min fail.

Why < would work?

因为内置<应用数字促销 ,而模板参数扣除则没有。

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

For every pair of promoted arithmetic types L and R , there exist candidate operator functions of the form

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

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


Actually, std::min should be able to deal with distinct types. The following 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 .

It 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) } 

so it needs the arguments to have the same type, but if you use (a<b) , so a could implicitly converted to a long long

Primitive types don't overload operators, so usual arithmetic conversions are applied and your int is converted to a long long, and the "<" has a valid meaning.

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

Example to show that your int is promoted to long 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 the binary operators (except shifts), if the promoted operands have different types, additional set of implicit conversions is applied, known as usual arithmetic conversions with the goal to produce the common type (also accessible via the std::common_type type trait)

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

Otherwise min function should return something. How could compiler guess which type should he return?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM