3

我正在检查具有类型特征的数值范围,并且无符号类型会生成警告。

Comparison of unsigned expression >= 0 is always true

如何在特定代码范围内禁用某些警告?我在 Clang 中使用了 GCC 样式#pragma,但这不起作用。这是我的代码。

template<typename originT, typename destinationT>
void
assertForNumericRange(const originT value)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored  "-Wtype-limits"
    assertWithReason(value >= std::numeric_limits<destinationT>::min());
    assertWithReason(value <= std::numeric_limits<destinationT>::max());
#pragma GCC diagnostic pop
}

笔记

目前,我将断言分为三组,浮点数、无符号整数、有符号整数。但如果可能的话,我希望将它们合二为一。

我正在使用 Xcode 5.0 测试版。在命令行中,它会报告:Apple LLVM version

5.0 (clang-500.1.58) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.3.0
Thread model: posix
4

3 回答 3

1

您使用的是哪个版本的 Clang?从Clang 用户手册中,它应该可以按照您的方式工作。但是您的范围断言不会按照您可能希望它们工作的方式工作:

第一个断言本身没有多大意义,如果destinationT是无符号的,所以 min 给出 0。要么originT也是无符号的,那么它显然不是负数,这是编译器警告你的。或者originT是有符号的,比较会将一个或两个操作数转换为其他类型,例如可能转换value为无符号(因此是正数)表示。

考虑例如

 assertForNumericRange<signed char, unsigned long>( (signed char)-1);  

(signed char)-1和之间的比较unsigned long会将 -1 提升为unsigned long,从而有效地给出以下 32 位长的断言:

assertWithReason((unsigned long)0xFFFFFFFF >= std::numeric_limits<destinationT>::min());
assertWithReason((unsigned long)0xFFFFFFFF <= std::numeric_limits<destinationT>::max());

两种比较都会给出正确的结果,而 -1 显然不在unsigned long's 值的范围内。

于 2013-06-20T06:58:49.943 回答
0

首先,请注意,对于浮点类型,例如

std::numeric_limits<float>::min()

返回最小正归一化值(>0),而对于整数类型

std::numeric_limits<T>::min()

返回最小的非正数 (<=0)。

浮点类型的最小负数为:

-std::numeric_limits<T>::max()

我认为你必须结合不同的numeric_limits 方法/成员(如is_integerand is_signed)和 if 语句,也可以摆脱你的警告。(从效率的角度来看)你不必担心得到一个过于复杂的函数,因为大多数检查将在编译时进行评估,并且不会影响执行时间。事实上,如果你可以避免在运行时进行一些不必要的检查,因为在编译时进行了一些检查,你的程序会更快。

您还应该使用std::is_same<T,U>::value, 并避免进一步检查是否属实。

于 2013-06-20T06:55:45.090 回答
0

检查我刚刚发布的这个问答。对我来说,它编译时没有警告,你应该在 Clang 上检查它。可以扩展到浮点类型。

于 2013-06-20T21:41:28.390 回答