Как заставить Clang игнорировать конкретное предупреждение в конкретном блоке?
Я проверяю числовой диапазон значений с типом признаков, а неподписанные типы генерируют предупреждение.
Comparison of unsigned expression >= 0 is always true
Как отключить некоторое предупреждение в определенном диапазоне кода? Я использовал стиль GCC #pragma
с Clang, но это не работает.
Вот мой код.
template<typename originT, typename destinationT>
void
assertForNumericRange(const originT value)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wtype-limits"
assertWithReason(value >= std::numeric_limits<destinationT>::min());
assertWithReason(value <= std::numeric_limits<destinationT>::max());
#pragma GCC diagnostic pop
}
Примечание
В настоящее время я разделил это утверждение на три группы: с плавающей запятой, unsigned int, signed int. Но я хочу объединить их в один, если это возможно.
Я использую Xcode 5.0 beta. В командной строке он сообщает об этом:
Версия Apple LLVM
5.0 (clang-500.1.58) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.3.0
Thread model: posix
Ответы
Ответ 1
Какую версию Clang вы используете? Из Руководство пользователя Clang оно должно работать так же, как и вы. Но ваши утверждения диапазона не будут работать так, как вы, вероятно, хотите, чтобы они работали:
Это первое утверждение само по себе не имеет большого смысла, если destinationT
не имеет знака, поэтому min дает 0. Либо originT
тоже без знака, то он явно не отрицательный, о чем компилятор предупреждает вас. Или originT
подписывается, сравнение будет конвертировать один или оба операнда в другие типы, например. возможно преобразование value
в беззнаковое (и, следовательно, положительное) представление.
Рассмотрим, например,
assertForNumericRange<signed char, unsigned long>( (signed char)-1);
Сравнение между (signed char)-1
и unsigned long
будет продвигать -1 до unsigned long
, эффективно давая следующие утверждения для 32-битной длины:
assertWithReason((unsigned long)0xFFFFFFFF >= std::numeric_limits<destinationT>::min());
assertWithReason((unsigned long)0xFFFFFFFF <= std::numeric_limits<destinationT>::max());
Оба сравнения дадут true, а -1 явно не находится в диапазоне значений unsigned long
.
Ответ 2
Прежде всего, имейте в виду, что:
std::numeric_limits<float>::min()
будет возвращать ноль, так как
std::numeric_limits<T>::min()
возвращает наименьшее не положительное число для целых типов, наименьшее не отрицательное число для типа с плавающей точкой
Минимальное отрицательное число для типа с плавающей запятой:
-std::numeric_limits<T>::max()
Я думаю, вам нужно объединить разные numeric_limits methods/members (например, is_integer
и is_signed
) и операторы if, а также получить избавиться от ваших предупреждений. (С точки зрения эффективности) Вам не нужно беспокоиться о том, чтобы получить слишком сложную функцию, так как большая часть проверок будет оцениваться во время компиляции и не будет влиять на время выполнения. Фактически, если вы можете избежать некоторых ненужных проверок во время выполнения из-за некоторых проверок, выполненных во время компиляции, ваша программа будет быстрее.
Вы также должны использовать std::is_same<T,U>::value
и избегать дальнейшей проверки, если это правда.
Ответ 3
Проверьте этот Q & A, который я только что опубликовал. Для меня он компилируется без предупреждений, вы должны проверить его на Clang. Возможно расширение до типов с плавающей точкой.