Каков наименее навязчивый способ заставить замолчать предупреждение со знаком / без знака в C ++? - PullRequest
0 голосов
/ 03 июня 2019

У меня есть программа связи с сокетом.Протокол заключается в том, что любая ошибка при записи является фатальной, поэтому соединение должно быть закрыто.Мой код ввода / вывода выглядит следующим образом:

auto const toWrite = buf.size() * sizeof(buf[0]);
auto nWritten = ::write(fd, buf.data, toWrite);

if (toWrite != nWritten)
{
    closeTheSocket();
}

Этот код дает warning: comparison between signed and unsigned integer expressions в булевом тесте.

Я понимаю зло больших / меньших сравнений со знаком и без знака, ноэто неизбежно здесь.Подпись для системного вызова ::write:

  #include <unistd.h>

  ssize_t write(int fd, const void *buf, size_t count);

Другими словами, моя переменная toWrite должным образом не подписана, а возвращенный nWritten подписан (-1 означает, чтоошибка).Мне все равно;все, кроме полной передачи, фатально для соединения.Кроме того, я не понимаю, как (in) тест на равенство между подписанным / неподписанным может быть опасным.

Я посмотрел здесь , здесь , здесь и здесь , но все вопросы касаются сравнений меньше, и все ответы "не делай этого".

Этот вопрос просит замолчать предупреждение, но кувалда "заставить замолчать все подписанные / неподписанные" сравнения нежелательна.

Как мне заставить замолчать только это предупреждение как можно менее навязчивым способом?

Ответы [ 2 ]

4 голосов
/ 03 июня 2019

Отделите обнаружение состояния ошибки от обнаружения неверной длины и используйте явное приведение

if ( nWritten < 0 ||
     static_cast<decltype(toWrite)>(nWritten) != toWrite )
{
   // handle problems
}

Небольшое редактирование: захват всех отрицательных значений в качестве ошибок для крошечного кусочка защиты будущего.

1 голос
/ 03 июня 2019

Если вы можете получить образец шаблона, другое возможное решение - написать функцию, которая обрабатывает каждый тип по-разному:

#include <type_traits>

template <class A, class B>
constexpr bool are_different(A a, B b)
{
    if constexpr (std::is_signed_v<A> and std::is_unsigned_v<B>)
    {
        if ( a < 0 )
            return true;
        else
            return std::make_unsigned_t<A>(a) != b;
    }
    else if constexpr (std::is_unsigned_v<A> and std::is_signed_v<B>)
    {
        if ( b < 0 )
            return true;
        else
            return a != std::make_unsigned_t<B>(b);
    }
    else
    {
        return a != b;
    }
}

int main()
{
    static_assert(are_different(1, 2));
    static_assert(!are_different(1ull, 1));
    static_assert(are_different(1, 2));
    static_assert(are_different(1u, 2));
    static_assert(are_different(1, 2u));
    static_assert(are_different(-1, -1u));
    static_assert(!are_different((long long)-1u, -1u));
}
...