New cast operators with additional features

Posted by Kaya Kupferschmidt • Friday, April 7. 2006 • Category: C++
C++ already has a rich set of casting operatos, ranging from old-style C casts, over static_cast, dynamic_cast and the almost-never-to-be-used reinterpret_cast. Sometimes it might be convenient to have something similar like a dynamic_cast but with another behaviour if the cast fails. For example one might want to get an exception if a specific cast is not possible.

It turns out that this is pretty easy using templates with the following code

template<class T,class S> T* throwing_cast(S* s) {
   T* result = dynamic_cast<T>(s);
   if (!result)
     throw bad_cast_exception();
   return result;
}

ClassA* a = new ClassB();
ClassB* b = throwing_cast<ClassB>(a);

But we still can do better than this, because we might want to configure which exception should be thrown on a casting failure. The code above can be easily modified to:


template<class T,class E,class S> T* throwing_cast(S* s) {
   T* result = dynamic_cast<T>(s);
   if (!result)
     throw E();
   return result;
}

ClassA* a = new ClassB();
ClassB* b = throwing_cast<ClassB,MyException>(a);

The next idea that might come to mind is to use a default-exception, that is something like follows:

template<class T,class E=BadCastException,class S> T* throwing_cast(S* s) {
   T* result = dynamic_cast<T>(s);
   if (!result)
     throw E();
   return result;
}

Unfortunately this is not possible, as only class templates may have default values for their template parameters. So we have to find a workaround. A (in my opinion rather neat) solution looks like follows:

template<class T,class E = Exception>
class throwing_cast {
public:
   template<class S>
   inline throwing_cast(S s) {
     T result = dynamic_cast<T>(s);
     if (!result)
       throw E();
     m_Object = result;
   };

   inline operator T() {
     return m_Object;
   };

private:
   T    m_Object;
};

Now yow can use this cast-operator in both ways:

ClassA* a = new ClassB();
ClassB* b =
   throwing_cast_old<ClassB*,Exception>((ClassA*)a);
ClassB* c = throwing_cast<ClassB*>((ClassA*)a);

6 Comments

Display comments as (Linear | Threaded)
  1. *Good trick, but shows the main drawback of C++ .. to get simple things, you need to do complex (and sometimes nasty) workarounds. When I looked into STL implementation, wow .. that was .. surely complex, party nasty.

    I do not get used to the XXXcast operators in C++ yet - yes, I cast by old C way. I could start using staticcast, which is OK, but I hate the underline in keyword - should not be there :-).

    The problem with e.g. reinterpretcast is that it can throw .. a badcast exception .. which is not in my hierarchy of exceptions (as I do not use STL). And what to do then? Add a catch to all try blocks? Not a good idea. Again, a simple thing gets very complicated in C++.

  2. *I would not say that you need complex workarounds in order to achieve simple things - with other languages you simply do not have any chance at all to do such things.

    Concerning the cast-operators, I had used the old-style cast operators for a long time time, but as soon as you use multiple base classes or virtual inheritance, a dynamic_cast operator is a must. Plus you can check in a very elegant way if a pointer to some base class is deriveable to another class at runtime - you will get back a null pointer if the object is not of the desired type.

    And reinterpretcast is something you should almost never use. Mst of the time, a staticcast will just do fine, it is essentially the same as old C-style casts. And for cross-casting in a hierarchy, a dynamic_cast is probably the only safe way.

    C++ is definately not simple, but it offers a lot of power. The only thing that is really, really broken are exception specifications. In every good book the author will explicitly discourage one to use them. That's really a pity, because I really liked the idea (which I first saw in Java) of specifying exceptions.

  3. *In other languages you have more modern features, with simple syntax (like C# from Microsoft). In C++, there are different possible ways, which is not always a benefit.

    The dynamic_cast and others require some RTTI information to be compiled, do not? I am not sure on this.

  4. *YOu are right about the many different ways of doing something in C++. Maybe I like that language simply because one can always find some new subtle features - no other language offers such a feeling of playing an adventure ;-)

    You are also right about dynamic_cast, it really needs RTTI information to be compiled in your files. But this is some useful information anyway, although it is still far too limited to be really useful.

    Maybe I will have a closer look at C# later this year, I am still thinking about using C# for building some GUI for my 3d engine. Do you happen to know if C# works well with unmanaged C++ code?

  5. *Hi Kaya,

    Actually, I did not try the C# a lot. Partly due to the lack of time, partly because I do not like the Microsoft's way of development (Visual everything .. I love working with files, no visual at all). Also, I do not want to spend my CPU cycles (and power watts) into interpreting something in the "managed" code (sounds like the programmer cannot manage it, so the machine MUST) .. I am an old-school assembler guy :-)

  6. *You are absolutely right there, I also like working with files more than with designers - on the other hands I am really not into GUI programming at all. In my experience creating a good GUI ttakes a lot of time, but is awfully boring to code.

    So what language would you propose?

Add Comment


Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
Standard emoticons like :-) and ;-) are converted to images.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

Markdown format allowed



A Simple Sidebar