Использование -Wtype-limit с универсальным кодом типа - PullRequest
1 голос
/ 04 ноября 2019

У меня есть функция, которая выполняет отрицательную проверку значения универсального типа (ну, я не хочу предполагать тип, он не обязательно шаблонизирован). Однако при включенном -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, если оно вызовет предупреждения, потому что значение, назначенное переменным этого типа, выпадет из диапазона типа. Кроме того, GCC выдает предупреждение, даже если я сначала приведу его к signed int. Поведение предупреждения не согласуется с самим собой, поэтому это похоже на ошибку. Clang вообще не выдает никаких предупреждений для этих типов проверок.

Но мне интересно, был ли способ обойти это, моя кодовая база строго совместима с C ++ 14, и мы застряли со старыми компиляторами GCC.

1 Ответ

1 голос
/ 04 ноября 2019

Я не уверен, что это окажет влияние на удобочитаемость, но вы можете переместить сравнение в контекст шаблона, используя общую лямбду. 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 s для временного отключения предупреждений, см. этот вопрос :

#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
...