views:

308

answers:

4

Sometimes I've got warnings with conversion from a longer type to a smaller type e.g.:

void f( unsigned short i ) // f - accept any numeric type
                           // smaller than std::vector<>::size_type
{}

std::vector < some_type > v;
..
f ( v.size() );

Usually I was using one of next solutions:

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() ) );

But on my present work boost not used and from last month asserts are disallowed.

What other safe ways you know for suppress this warning?
Any pitfalls in discribed ways?

PS: It is not always possible to change the signature of f, also sometimes really should accept small numeric type.

EDITED: I want to make conversion as safe as possible.

+6  A: 

Why cast in the first place? The vector's size is typically an unsigned integer. If possible, I'd say update the function signature. Warnings are not meant to be suppressed, rather addressed.

dirkgently
It is impossible to change function signature. I wants avoid warning as safe as this possible.
bb
In first place static_cast helps to supress compiler warning.
bb
You cannot both cast and assume that you are ok. The cast _will_ take out the warning. Suit yourself.
dirkgently
bb, if it is impossible to change the function signature - then you can't fix it. just make it take unsigned long if you want to be safe.
Johannes Schaub - litb
+2  A: 

I will now repeat my mantra again: If your code contains casts, there is probably something wrong with the code or the design and you should examine both with a view to removing the cast.

BTW, you upvoted this the last time I posted it!

anon
Yes. But we have old code, and not all places could be changed.
bb
Also most of this code wrong and have bad design:)
bb
Even so, you may want to use vectors that you _know_ contain less than e.g. 256 elements, so all your domain specific functions use unsigned char. You can't go without a cast there.
xtofl
+2  A: 

As size() usually returns an unsigned integer, it should be quite safe to typecast it to a signed one.

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

Otherwise change the function signature, if it is possible.

Jens
Yes but we should convert bigger type to smaller.
bb
+3  A: 

The only safe way to deal with this is to ensure that you do not have a loss of conversion at runtime. The assert code will only work during debug builds and will allow for a conversion loss in retail builds. The conversion loss is bad because it will pass around a completely incorrect size for the vector.

What you really need is a mechanism to prevent you from creating data loss. I reccomend using a class like SafeInt. This will prevent a conversion which overflows or underflows by means of throwing an exception.

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

JaredPar
Thank you, usege from your exmaple similar on boost::numeric_cast but without boost.
bb
I like Jared's suggestion. It shouldn't be too difficult to roll your own ad-hoc version of SafeInt if you're not allowed to include any 3rd party libraries.
veefu
@veefu, it's licensed under MS-PL which means it should be includable in most any project
JaredPar