请考虑以下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/

10-11 23:07
查看更多