Я получаю предупреждение за сравнение со знаком и без знака при сравнении std::abs(int)
против unsigned
, И действительно, std::abs
возвращает подписанные значения. Почему был сделан этот выбор? Это решило бы проблему отрицательных значений, абсолютное значение которых нельзя представить в виде со знаком.
И затем, есть ли что-то более чистое (т.е. без приведения), чем это, чтобы избежать предупреждений?
#include <cassert>
#include <cstdlib>
// max(1, lhs + rhs). (lhs must be > 0)
unsigned add(unsigned lhs, int rhs)
{
return
(0 < rhs || static_cast<unsigned>(-rhs) < lhs
? rhs + lhs
: 1);
}
int main()
{
assert(add(42, -41) == 1);
assert(add(42, 0) == 43);
assert(add(42, 1) == 43);
assert(add(42, -51) == 1);
}
Короткий ответ заключается в том, что это сделано для того, чтобы возвращаемый тип abs
совпадает с его типом ввода. Это именно то, что вы хотите, большую часть времени.
В основном, когда вы вызываете abs, вы имеете дело с уравнением, в котором все элементы имеют одинаковый тип (или вы получите предупреждения), и вы хотите использовать величину некоторой переменной в этом уравнении. Это не значит, что вы хотите изменить тип одной из переменных в вашем уравнении. Это дало бы вид проблем / предупреждений, которые вы упоминаете.
Итак, короче говоря, более распространенным и более естественным является использование одного и того же типа ввода и вывода при запросе абсолютного значения переменной со знаком. Величина значения обычно не используется в качестве индекса.
В C ++ 11 вы могли бы написать свой собственный, чтобы сделать для автоматического приведения:
#include <utility>
template< typename T >
typename std::make_unsigned<T>::type abs( T x )
{
//We need to cast before negating x to avoid the overflow.
return x < 0? -static_cast<std::make_unsigned<T>::type>(x) : x;
}
Я попробовал это с опциями -Wall, не получил предупреждений.
Это не выбор, это определение. abs реализован через шаблон, который возвращает тип, в котором было сохранено исходное значение. Результат всегда будет действительным, поскольку абсолютное значение целого числа со знаком всегда будет соответствовать исходному типу данных. Явного приведения к целевому типу данных должно быть достаточно, чтобы избавиться от любых предупреждений …