为什么std::abs返回有符号类型



当我比较std::abs(int)unsigned时,我得到了有符号与无符号比较的警告。事实上,std::abs返回有符号的值。为什么做出这样的选择?它可以解决绝对值不能用符号类型表示的负值的问题。

然后,是否有比这更干净(即不强制转换)的方法来避免警告?

#include <cassert>
#include <cstdlib>
// max(1, lhs + rhs). (lhs must be > 0)
unsigned add(unsigned lhs, int rhs)
{
  return
    (0 < rhs || static_cast<unsigned>(-rhs) < lhs
     ? rhs + lhs
     : 1);
}
int main()
{
  assert(add(42, -41) == 1);
  assert(add(42, 0) == 43);
  assert(add(42, 1) == 43);
  assert(add(42, -51) == 1);
}

简短的回答是,这样做是为了使abs的返回类型与其输入类型相同。大多数情况下,这正是你想要的。

大多数情况下,当调用abs时,您正在处理一个所有元素都是相同类型的方程(否则您会得到警告),并且您希望在该方程中使用某些变量的大小。这并不意味着你要改变方程中某个变量的类型。这将给出你提到的那种问题/警告。

因此,简而言之,在要求有符号变量的绝对值时,希望相同的输入和输出类型是更常见和更自然的。值的大小通常不用作索引

在c++11中你可以自己写一个自动强制转换:

#include <utility>
template< typename T >
typename std::make_unsigned<T>::type  abs( T x )
{
    //We need to cast before negating x to avoid the overflow.
    return x < 0? -static_cast<std::make_unsigned<T>::type>(x) : x;
}

我尝试使用-Wall选项,没有任何警告。

这不是选择,这是定义。Abs是通过模板实现的,该模板返回存储原始值的类型。结果将始终有效,因为有符号整数的绝对值将始终适合其原始数据类型。对目标数据类型的显式强制转换应该足以消除任何警告…

最新更新