将-Wtype-limits与类型通用代码一起使用

问题描述 投票:0回答:1

我有一个对通用类型的值执行否定检查的函数(我不想假设该类型,它不一定是模板化的)。但是,启用-Wtype-limits时,编译器会抱怨有关类型是否为无符号类型的否定检查。如果类型可能更改为带符号的类型,则删除否定检查是一个坏主意,并且禁用警告也不是理想的选择,因为它可能会引起合法问题。

using example_t = uint8_t;   // could be int8_t or int64_t or really whatever integer type that can store values 0 - 8.

void example(example_t value) {
    if (value < 0 || value >= 9) {  // <-- errors on the 'value < 0' check
        throw std::invalid_argument("some error message");
    }
    // continue processing ...
}

即使我使用C ++ 17并使用if constexpr(std::is_unsigned<example_t>::value)来保护警告的检查,它仍然会发出警告。我注意到,如果GCC会触发警告,则不会为if constexpr输出的代码发出警告,因为分配给这些类型的变量的值将超出该类型的范围。另外,即使我先将其强制转换为signed int,GCC也会发出警告。警告行为与其自身不一致,因此这似乎是一个错误。 Clang对这些类型的检查完全不发出警告。

但是我想知道是否有办法解决,我的代码库严格符合C ++ 14,并且我们仍然使用旧的GCC编译器。

c++ gcc clang c++14
1个回答
0
投票

我不确定是否值得在可读性上产生影响,但是您可以使用通用lambda将比较移到模板上下文中。 GCC不会在模板代码中对此发出警告:

if ([](auto v){return v < 0;}(value) || value >= 9)

或者也许更好地编写一个函数:

template<typename T>
constexpr bool is_negative(T t) { return t < 0; }

并使用它:

if (is_negative(value) || value >= 9)

或仅使用std::less也不会警告:

if (std::less()(value, 0) || value >= 9)

GCC还具有#pragma来暂时禁用警告,请参阅this question

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wtype-limits"
if (value < 0 || value >= 9) {
    throw std::invalid_argument("some error message");
}
#pragma GCC diagnostic pop
© www.soinside.com 2019 - 2024. All rights reserved.