Я получаю предупреждение за сопоставленное сравнение без знака, когда сравниваю std::abs(int)
с unsigned
. И действительно, std::abs
возвращает подписанные значения. Почему этот выбор был сделан? Он решил бы проблему отрицательных значений, абсолютная величина которых не может быть представлена в подписанном типе.Почему 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);
}
Я сомневаюсь, что это оказало большое влияние на стандартное обоснование, но на самом деле не гарантируется, что 'unsigned' может представлять каждое абсолютное значение' int'. Теоретически у вас может быть соответствующая реализация, в которой 'int' является дополнением 33 бит 2, а' unsigned' - 32 бита. В этой реализации ни 'int', ни' unsigned' не могут представлять абсолютное значение 'INT_MIN'. Не уверен, почему вы хотите такую реализацию, конечно, но это законно, и поэтому ваше предложение не * строго * решает проблему. Стандарт по-прежнему допускает реализацию, где вы не можете выполнить 'abs (INT_MIN)'! –
И на практике тот факт, что есть одно значение 'int', на которое вы не можете выполнить' abs', на самом деле не является более сложным, чем тот факт, что есть одно значение 'int', на которое вы не можете сделать '--'. Точно так же значение, на которое вы не можете выполнить '++'. Авторы C и C++ не слишком ненавидят неопределенное поведение переполнения, чтобы удалить его. –
@SteveJessop Как это возможно, учитывая §3.9.1-3 (такое же количество хранения и одно и то же представление объекта для 'unsigned int' и' int')? –