Преобразование из «xxxx» в «yyyy», возможная потеря данных, подавление?

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

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, также иногда действительно следует принимать мелкий числовой тип.

ОТРЕДАКТИРОВАНО: я хочу сделать конверсию максимально безопасной.


person bayda    schedule 04.04.2009    source источник
comment
Какова сигнатура функции f? Как только мы это узнаем, мы можем начать думать о том, почему вы получаете предупреждение и что мы можем с этим сделать.   -  person Michael Kristofik    schedule 04.04.2009
comment
что не так со static_cast?   -  person jalf    schedule 04.04.2009
comment
@jalf: ничего, но я хочу сделать конвертацию максимально безопасной. @Kristo: вопрос отредактирован.   -  person bayda    schedule 04.04.2009
comment
Тогда вы можете добавить эту информацию к своему вопросу. Ваш вопрос только спрашивает, как подавить предупреждение. Но в этом случае я предлагаю посмотреть, сможете ли вы скопировать код boost::numeric_cast. Создайте свой собственный, который делает то же самое, так как это именно то, что вам нужно.   -  person jalf    schedule 04.04.2009
comment
Почему утверждения больше не разрешены? Потому что слишком многие из них срабатывают во время выполнения кода? Если да, то компания стреляет в мессенджер, а код менее безопасен, чем раньше.   -  person Jonathan Leffler    schedule 04.04.2009
comment
утверждения за последний месяц запрещены. - Веселый! У вашего босса остроконечные волосы?   -  person shoosh    schedule 04.04.2009
comment
bb, я рекомендую typedef char check[numeric_limits‹vector_type::size_type›::digits ‹= numeric_limits‹unsigned int›::digits];   -  person Johannes Schaub - litb    schedule 04.04.2009
comment
@shoosh: Боюсь, у него есть только один аргумент, который он утверждает в производстве. Я рано увидел забытые директивы NDEBUG. Когда у тебя будет такой же опыт, как у меня, ты меня поймешь=)   -  person bayda    schedule 04.04.2009
comment
@litb: не могли бы вы расширить свою идею?   -  person bayda    schedule 04.04.2009
comment
bb я не уверен, что я должен расширить? это уже была вся идея хаха   -  person Johannes Schaub - litb    schedule 04.04.2009
comment
@litb: я уже понял этот трюк. Ницца. Но это проверка во время компиляции, предупреждения уже помогают найти возможные проблемы без дополнительных манипуляций. Но иногда мы знаем, что все должно работать, и я хочу юридически защищенную конвертацию.   -  person bayda    schedule 04.04.2009


Ответы (4)


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

person dirkgently    schedule 04.04.2009
comment
Изменить сигнатуру функции невозможно. Я хочу избежать предупреждения настолько безопасно, насколько это возможно. - person bayda; 04.04.2009
comment
Во-первых, static_cast помогает подавить предупреждения компилятора. - person bayda; 04.04.2009
comment
Вы не можете одновременно бросить и предположить, что вы в порядке. Приведение удалит предупреждение. Одевают. - person dirkgently; 04.04.2009
comment
bb, если невозможно изменить сигнатуру функции - то и исправить нельзя. просто сделайте так, чтобы unsigned заняло много времени, если вы хотите быть в безопасности. - person Johannes Schaub - litb; 04.04.2009

Единственный безопасный способ справиться с этим — убедиться, что у вас нет потери конверсии во время выполнения. Код утверждения будет работать только во время отладочных сборок и допускает потерю конверсии в розничных сборках. Потери при преобразовании плохи, потому что они будут передавать совершенно неправильный размер вектора.

Что вам действительно нужно, так это механизм, предотвращающий потерю данных. Я рекомендую использовать такой класс, как 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

person JaredPar    schedule 04.04.2009
comment
Спасибо, используйте пример из вашего примера, похожий на boost::numeric_cast, но без повышения. - person bayda; 04.04.2009
comment
Мне нравится предложение Джареда. Не должно быть слишком сложно развернуть собственную специальную версию SafeInt, если вам не разрешено включать какие-либо сторонние библиотеки. - person veefu; 05.04.2009
comment
@veefu, он лицензирован под MS-PL, что означает, что его можно включать в большинство проектов. - person JaredPar; 05.04.2009

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

Кстати, вы проголосовали за это в последний раз, когда я опубликовал это!

person Community    schedule 04.04.2009
comment
Да. Но у нас старый код, и не все места можно было поменять. - person bayda; 04.04.2009
comment
Тем не менее, вы можете захотеть использовать векторы, которые, как вы знаете, содержат меньше, чем, например. 256 элементов, поэтому все функции вашего домена используют беззнаковые символы. Там без гипса не обойтись. - person xtofl; 04.04.2009

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

f(static_cast<expected-type>(v.size()));

В противном случае измените сигнатуру функции, если это возможно.

person Jens Luedicke    schedule 04.04.2009
comment
Да, но мы должны преобразовать больший шрифт в меньший. - person bayda; 04.04.2009