|
A New Cast For C++, With Rating
Submitted by |
Following my previous TOTD thread, I began thinking about what I think are
the most important things you need to consider when you're about to
implement a technique using something "really smart", especially in C++:
1- The ease of use of the technique. If it's hard to use, it won't be used.
2- The ease of understanding how it works, black-box style. If its
functioning is obscure, users will make too many mistakes.
3- The clarity of error messages when users do make mistakes, typos, etc...
4- The ease, for you, of understanding the innards of the technique. If you
came, say, a year later, and you had to mess with it, how bad would it be?
5- The ease, for another programmer, of understanding the innards. In case
you jump from a plane and forget the parachute, so to speak.
(Am I forgetting anything critical here?)
I believe that, with those things, you can measure the desirability of
actually doing it. It should be interesting if we start rating our posts
like that.
Anyway, I'd like to post a nice tip. It's not from me, originally. I saw it
in a presentation by one of the developers at Microsoft working on the
MSVC++ debugger, so the actual credit should go to him. I just don't
remember his name. He proposed a new cast, called checked_cast. It would
work just as a static_cast, except that it would use dynamic_cast to catch
programming errors in debug mode. I modified it somewhat, so it ended up
like this:
template < class TypeTo, class TypeFrom
__forceinline TypeTo checked_cast(TypeFrom *t) {
#if (defined(CHECKED_BUILD) || !defined(NDEBUG))
if (t) {
TypeTo dtto = dynamic_cast<TypeTo(t);
TypeTo stto = static_cast<TypeTo(t);
ASSERT(dtto != 0);
ASSERT(dtto == stto);
return stto;
} else {
return 0;
}
#else
return static_cast<TypeTo(t);
#endif
} |
If you try to perform an up-cast with checked_cast when in debug mode,
it'll assert out. In release mode, it'll assume the cast is correct, and so
it performs it in the most efficient manner.
So... how should we rate this? My personal opinion is:
1- Very good.
2- Very good.
3- Very good (MSVC).
4- Very good. (That's for me ;-)
5- Good, I believe. It does require some understanding of templates, though.
To test the error message generation I used the following code in MSVC++ 6.0:
struct A {};
struct B: A {};
void func2()
{
static_cast(8);
checked_cast(8);
static_cast<2;
checked_cast<2;
static_cast<2();
checked_cast<2();
A a;
B *pb;
pb = static_cast<A*(&a);
pb = checked_cast<A*(&a);
pb = static_cast<int*(&a);
pb = checked_cast<int*(&a);
pb = static_cast<int(&a);
pb = checked_cast<int(&a);
pb = static_cast<B(&a);
pb = checked_cast<B(&a);
// Correct form.
pb = static_cast<B*(&a);
pb = checked_cast<B*(&a);
} |
In all cases the message was marked on the proper line of code, and, in all
the cases after defining the local variables, I got for static_cast the
same error message that I got for checked_cast.
Salutaciones,
JCAB
|
The zip file viewer built into the Developer Toolbox made use
of the zlib library, as well as the zlibdll source additions.
|