gcc警告" -WOverflow"

时间:2017-01-16 14:33:09

标签: c++ gcc

请考虑以下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() ......

1 个答案:

答案 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将函数约束为仅在模板结算时进行编译。