mikejsavage.co.uk • About • Archive • RSS • Thanks for blocking ads! Blocking ads owns: AdGuard for Safari / uBlock Origin for everything else
C style casts are not awesome. Their primary use is to shut up conversion warnings when you assign a float to an int etc. This is actually harmful and can mask actual errors down the line when you change the float to something else and it starts dropping values in the middle of your computation.
Some other nitpicks are that they are hard to grep for and can be hard to parse.
In typical C++ fashion, static_cast
and friends solve the nitpicks but
do absolutely nothing about the real problem. Fortunately, C++ gives us
the machinery to solve the problem ourselves. This first one is copied
from Charles Bloom:
template< typename To, typename From >
inline To checked_cast( const From & from ) {
To result = To( from );
ASSERT( From( result ) == from );
return result;
}
If you're ever unsure about a cast, use checked_cast
and it will
assert if the cast starts eating values. Even if you are sure, use
checked_cast
anyway for peace of mind. It lets you change code freely
without having to worry about introducing tricky bugs.
Another solution is to specify the type you're casting from as well as the type you're casting to. The code for this is a bit trickier:
template< typename S, typename T >
struct SameType {
enum { value = false };
};
template< typename T >
struct SameType< T, T > {
enum { value = true };
};
#define SAME_TYPE( S, T ) SameType< S, T >::value
template< typename From, typename To, typename Inferred >
To strict_cast( const Inferred & from ) {
STATIC_ASSERT( SAME_TYPE( From, Inferred ) );
return To( from );
}
You pass the first two template arguments and leave the last one to
template deduction, like int a = strict_cast< float, int >( 1 );
(which explodes). I've not actually encountered a situation where this
is useful yet, but it was a fun exercise.
Maybe it's good for casting pointers?