Сравнение подписанного и неподписанного.Static_cast - единственное решение? - PullRequest
0 голосов
/ 29 ноября 2018

Я использую сторонние контейнеры, которые используют int для хранения размера.Я также использую контейнеры stl, которые используют size_t для хранения размера.

Мне очень часто в моем коде приходится использовать оба в одном и том же цикле, как, например:

// vec is std::vector
// list is the third party container
assert(vec.size() == list.size()); // warning
for(size_t i = 0; i < vec.size(); i++)
{
    vec[i] = list[i]; // warning
}

исправить я должен либо выполнить приведение к стилю функций, что мне сказали, что это скрытое приведение к стилю C.

// vec is std::vector
// list is the third party container
assert(int(vec.size()) == list.size());
for(size_t i = 0; i < vec.size(); i++)
{
    vec[i] = list[int(i)];
}

Или я могу сделать еще более уродливое решение, которое все рекомендуют.Статическое приведение.

// vec is std::vector
// list is the third party container
assert(static_cast<int>(vec.size()) == list.size());
for(size_t i = 0; i < vec.size(); i++)
{
    vec[i] = list[static_cast<int>(i)];
}

Я действительно не хочу static_cast.

  • Может ли неявное преобразование в этом конкретном сценарии быть опасным?
  • Будет ли стиль функции в моем случае нормальным?
  • Если static_cast действительно является единственным безопасным решением.Должен ли я разыграть int до size_t или size_t до int?

Спасибо.

1 Ответ

0 голосов
/ 29 ноября 2018

Двоичные операторы (operator== здесь) преобразуют целые числа со знаком в беззнаковые, если один из аргументов не имеет знака.Подписанное отрицательное целое число превращается в большое положительное.

Количество элементов контейнера не должно быть отрицательным, чтобы не нарушать принцип наименьшего удивления.Таким образом, неявное преобразование должно быть безопасным.Но обязательно проверьте реализацию / документацию int size() const.

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

#include <type_traits>

template<class T>
inline typename std::make_unsigned<T>::type as_unsigned(T a) {
    return static_cast<typename std::make_unsigned<T>::type>(a);
}

, а затем:

assert(vec.size() == as_unsigned(list.size()));
...