14

当我将 astd::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);
}
4

3 回答 3

9

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

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

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

于 2013-04-19T09:24:50.990 回答
3

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

于 2013-04-19T09:15:10.237 回答
3

在 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 选项,没有收到任何警告。

于 2013-04-19T09:41:06.647 回答