请考虑以下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分支发出-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()
......
答案 0 :(得分:1)
这里的问题是
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将函数约束为仅在模板结算时进行编译。