繁体   English   中英

为什么小于运算符接受不同类型的参数而std :: min不是?

[英]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);

---

感谢chris函数重载过后的注释模板参数推断不会将转换考虑在内。 一个模板参数不能匹配两种类型

所以std::min失败了。

为什么<会起作用?

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

正如在其他答案中所解释的那样,原因是std::min要求参数的类型在执行演绎时是相同的,而<暗示通常的算术转换(§5.9/ 2),这将确保类型转换为“共同分母”。 请注意§13.6/ 12如何将内置运算符列为候选运算符:

对于每对提升的算术类型LR ,存在该形式的候选运算符函数

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

其中LR是类型LR之间通常的算术转换的结果。


实际上, std::min应该能够处理不同的类型。 以下是一种更现代的方法:

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)...);
}

演示

这是因为std::min是一个模板函数。

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

所以它需要具有相同类型的参数,但是如果你使用(a<b) ,那么a可以隐式转换为long long

原始类型不会重载运算符,因此应用通常的算术转换 ,并将int转换为long long,“<”具有有效含义。

您甚至无法为基本类型重载运算符: https//isocpp.org/wiki/faq/intrinsic-types#intrinsics-and-operator-overloading

示例显示您的int被提升为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;
}

文档http://en.cppreference.com/w/cpp/language/operator_arithmetic

对于二元运算符(除了移位),如果提升的操作数具有不同的类型,则应用另外一组隐式转换,称为通常的算术转换,目标是生成公共类型(也可通过std :: common_type类型特征访问)

<运算符是二进制的,因此编译器可以将参数转换为相同的类型并进行比较。

否则min函数应返回一些东西。 编译器如何猜测他应该返回哪种类型?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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