Beakie
Beakie

Reputation: 1999

dynamic_cast not throwing exceptions as expected

Based on this answer...

Finding the type of an object in C++

...I wrote this code:

        static TVALUE getUpperBound()
        {
            SomeStruct<TVALUE>* t;

            try
            {
                dynamic_cast<SomeStruct<bool>*> (t);
                return 1;
            }
            catch (int e)
            {
            }

            try
            {
                dynamic_cast<SomeStruct<unsigned char>*> (t);
                return 255;
            }
            catch (int e)
            {
            }

            try
            {
                dynamic_cast<SomeStruct<unsigned int>*> (t);
                return 65535;
            }
            catch (int e)
            {
            }

            return 0;
        }

But it doesn't work :-/

I know there are OTHER ways to do this (using includes) but I need to get this technique working.

I can't include any includes in my code (it's a long story, but I simply can't)... hence this attempt at doing something that could be done easily with climits or typeinfo.

Can anyone please explain to me why this doesn't work?

Edit 1:

Thanks guys. I missed the reference vs pointer bit.

This works now:

template <typename TVALUE>
TVALUE getUpperBound()
{
    SomeStruct<TVALUE>* t;

    if (dynamic_cast<SomeStruct<bool>*> (t) != nullptr)
        return 1;
    if (dynamic_cast<SomeStruct<unsigned char>*> (t) != nullptr)
        return 255;
    if (dynamic_cast<SomeStruct<unsigned int>*> (t) != nullptr)
        return 65535;

    return 0;
}

Edit 2:

I tried @StilesCrisis advice and used template specialization

template <typename TVALUE>
TVALUE getUpperBound();

template <>
bool getUpperBound<bool>()
{
    return 1;
}

template <>
unsigned char getUpperBound<unsigned char>()
{
    return 255;
}

template <>
unsigned int getUpperBound<unsigned int>()
{
    return 65535;
}

Works a charm. Much better implementation. Thanks!

Upvotes: 0

Views: 253

Answers (2)

StilesCrisis
StilesCrisis

Reputation: 16290

You are casting to a pointer. bad_cast is only generated when casting to a reference.

You can just check for nullptr if casting to a reference isn't desirable.

Upvotes: 1

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385174

dynamic_cast only throws exceptions on failure if its template argument is a reference type.
When it's a pointer type, dynamic_cast instead evaluates to NULL on failure.

This is made very clear in the preferred language reference, for which you could simply have Googled:

5c) Otherwise, the runtime check fails. If the dynamic_cast is used on pointers, the null pointer value of type _new_type_ is returned. If it was used on references, the exception std::bad_cast is thrown.

I also don't understand why you expect an int to be thrown, rather than something that derives std::exception. Perhaps you were hoping that return in a try block jumps to the matching catch block? It doesn't.

Upvotes: 4

Related Questions