Почему std :: abs возвращает подписанные типы

Я получаю предупреждение за сравнение со знаком и без знака при сравнении 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);
}

10

Решение

Короткий ответ заключается в том, что это сделано для того, чтобы возвращаемый тип abs совпадает с его типом ввода. Это именно то, что вы хотите, большую часть времени.

В основном, когда вы вызываете abs, вы имеете дело с уравнением, в котором все элементы имеют одинаковый тип (или вы получите предупреждения), и вы хотите использовать величину некоторой переменной в этом уравнении. Это не значит, что вы хотите изменить тип одной из переменных в вашем уравнении. Это дало бы вид проблем / предупреждений, которые вы упоминаете.

Итак, короче говоря, более распространенным и более естественным является использование одного и того же типа ввода и вывода при запросе абсолютного значения переменной со знаком. Величина значения обычно не используется в качестве индекса.

8

Другие решения

В 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, не получил предупреждений.

3

Это не выбор, это определение. abs реализован через шаблон, который возвращает тип, в котором было сохранено исходное значение. Результат всегда будет действительным, поскольку абсолютное значение целого числа со знаком всегда будет соответствовать исходному типу данных. Явного приведения к целевому типу данных должно быть достаточно, чтобы избавиться от любых предупреждений …

2
По вопросам рекламы [email protected]