我正在检查数字值范围与类型特征,无符号类型生成警告。
Comparison of unsigned expression >= 0 is always true
如何在特定代码范围禁用某些警告?我使用GCC风格的#pragma
和Clang,但这不起作用。这是我的代码。
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
}
注意
目前,我将断言分为三组,浮点数,unsigned int,signed int。但如果可能的话,我希望将它们合并为一个。
我正在使用Xcode 5.0 beta。在命令行中,它报告此:Apple LLVM版本
5.0 (clang-500.1.58) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.3.0
Thread model: posix
您使用的是哪个版本的Clang?从the Clang User Manual它应该完全按照你的方式工作。但是你的范围断言不会像你希望它们工作的方式那样工作:
第一个断言本身没有多大意义,如果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
的值范围内。
检查this Q&A I just posted。对我来说,它编译没有警告,你应该在Clang上检查它。可以扩展到浮点类型。
首先,请注意浮点类型,例如
std::numeric_limits<float>::min()
返回minimum positive normalized value(> 0),而对于整数类型
std::numeric_limits<T>::min()
返回最小的非正数(<= 0)。
浮点类型的最小负数是:
-std::numeric_limits<T>::max()
我认为你必须结合不同的numeric_limits methods/members(如is_integer
和is_signed
)和if语句,以摆脱你的警告。 (从效率的角度来看)您不必担心获得过于复杂的功能,因为大多数检查将在编译时进行评估,并且不会影响执行时间。实际上,如果由于在编译时进行了一些检查,你可以在运行时避免一些不必要的检查,那么你的程序会更快。
您还应该使用std::is_same<T,U>::value
,并且如果确实如此,请避免进一步检查。