请考虑以下C++ 98代码段:
#include <iostream>
#include <limits>
template <typename T> T myLower() {
if (std::numeric_limits<T>::is_integer) {
return std::numeric_limits<T>::min();
} else {
return -std::numeric_limits<T>::max();
}
}
int main(int argc, char *argv[]) {
std::cout << (int)myLower<uint8_t>() << "\n";
return 0;
}
用
g++ test.cpp && ./a.out
编译时,它可以按预期工作:打印0。但是,当使用任何优化方式(向上为-O1
,也为-Os
)进行编译时,会针对else-branch发出-Woverflow
警告,警告仅适用于浮点数:g++ test.cpp -Wall -O1 && ./a.out
test.cpp: In instantiation of ‘T myLower() [with T = unsigned char]’:
test.cpp:16:46: required from here
test.cpp:9:16: warning: large integer implicitly truncated to unsigned type [-Woverflow]
retval = -std::numeric_limits<T>::max();
~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0
对于
uint16
,这也会失败,所有其他类型均应正常工作。据我所知std::numeric_limits<uint8_t>::is_integer
应该是一个编译时常量-为什么根本不编译else-branch?警告不严重或我错过了什么吗?嗯,这发生在gcc5和gcc6中。
谢谢!
PS:我知道将来到达这里时会有
std::numeric_limits<>::lowest()
... 最佳答案
这里的问题是
if (std::numeric_limits<T>::is_integer)
不限制
T
可以是什么。这意味着else
brance总是被编译,并且即使从未到达该分支也可能导致操作溢出,从而触发警告。如果您使用的是C++ 17,则可以使用
if constexpr
template <typename T> T myLower() {
if constexpr (std::numeric_limits<T>::is_integer) {
return std::numeric_limits<T>::min();
} else {
return -std::numeric_limits<T>::max();
}
}
仅根据
if
条件编译else
块或constexpr
块。在C++ 17之前,您必须使用SFINAE来约束该函数,使其仅在模板解析后才能编译。关于c++ - gcc警告 “-WOverflow”,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41678731/