Иногда я получаю предупреждения с преобразованием из более длинного типа в меньший, например:
void f( unsigned short i ) // f - accept any numeric type
// smaller than std::vector<>::size_type
{}
std::vector < some_type > v;
..
f ( v.size() );
Обычно я использовал одно из следующих решений:
assert( v.size() <= std::numeric_limits< unsigned short >::max() );
f( static_cast< unsigned short >( v.size() ) );
or
f( boost::numeric_cast< unsigned short >( v.size() ) );
Но на моей текущей работе буст не используется и с прошлого месяца утверждения запрещены.
Какие другие безопасные способы подавления этого предупреждения вы знаете?
Есть ли подводные камни в описанных способах?
PS: Не всегда возможно изменить подпись f, также иногда действительно следует принимать мелкий числовой тип.
ОТРЕДАКТИРОВАНО: я хочу сделать конверсию максимально безопасной.
Ответ 1 · рейтинг 7 · dirkgently
Почему кастинг в первую очередь? Размер вектора обычно представляет собой целое число без знака. Если возможно, я бы сказал, обновите сигнатуру функции. Предупреждения не предназначены для подавления, а для устранения.
Ответ 2 · рейтинг 3 · JaredPar
Единственный безопасный способ справиться с этим - убедиться, что у вас нет потери конверсии во время выполнения. Код утверждения будет работать только во время отладочных сборок и допускает потерю конверсии в розничных сборках. Потери при преобразовании плохи, потому что они будут передавать совершенно неправильный размер вектора.
Что вам действительно нужно, так это механизм, предотвращающий потерю данных. Я рекомендую использовать такой класс, как SafeInt. Это предотвратит преобразование, которое переполняется или недополняется посредством создания исключения.
SafeInt<size_t> size = v.size();
f((unsigned short)size); // Throws if size can't fit in an unsigned short
SafeInt: http://www.codeplex.com/SafeInt
Ответ 3 · рейтинг 2 · Community
Теперь я повторю свою мантру еще раз: если ваш код содержит приведения типов, вероятно, что-то не так с кодом или схемой, и вам следует проверить и то, и другое, чтобы удалить приведения типов.
Кстати, вы проголосовали за это в последний раз, когда я опубликовал это!
Ответ 4 · рейтинг 2 · Jens Luedicke
Поскольку size() обычно возвращает целое число без знака, должно быть вполне безопасно приводить его к типу со знаком.
f(static_cast<expected-type>(v.size()));
В противном случае измените сигнатуру функции, если это возможно.