如何避免std :: abs的意外结果?

时间:2018-05-05 23:40:25

标签: c++ language-lawyer

我遇到了一些std::abs可能产生意外结果的方式的不同示例:

  1. 这个问题(On the std::abs function)指出<cstdlib>为整数类型提供重载,而<cmath>为浮点类型提供重载。未能包含正确的标头会给出未定义的行为,允许编译器静默接受
  2. C ++ Defect report 2735指出C ++ 11和C ++ 14标准在技术上要求std::abs(short)返回double,尽管大多数编译器会忽略相关的措辞并返回{ {1}}。此问题的解决方案表明在C ++ 17中更改了措辞,以便int返回std::abs(short)
  3. 这个问题的答案(When do I use fabs and when is it sufficient to use std::abs?)指出依赖int会导致难以发现的错误,因为(在现代C ++中)引入std::abs的标题允许引入全局std::abs函数(可能有也可能没有相同的重载),并且很容易意外使用abs而不是abs
  4. 我所知道的修复是:

    1. 避免未定义的行为:如果评估std::abs则包括<cstdlib>,评估std::abs([integral type])
    2. 时包括<cmath>
    3. 两种选择:
      • 使用C ++ 17或pre-(C ++ 11)
      • 解决std::abs([floating point type])可能返回std::abs(short)int这一事实,具体取决于编译器对C ++ 11 / C ++ 14标准的符合性
    4. 两种选择:
      • 将gcc传递给标记double,以便–Wconversion之类的调用在编译时触发警告
      • 使用诀窍(改编自上午(Disable math.h crap when working with cmath)的答案)来制作全球abs(2.0)不明确的
    5. 诀窍:

      abs

      问题:是否有理由更喜欢其中一种解决方案发布3?这些修复中的任何一个都会引入我需要注意的其他潜在问题吗?

1 个答案:

答案 0 :(得分:5)

创建自己的头文件,定义inline函数absolute,后者又包含所有正确的标头并修复返回类型的错误,并调用std::abs

然后,请勿使用absstd::abs(或任何名为abs的令牌)。在git commit(或您使用的任何版本管理系统)中执行此操作,而不是在该文件中。