Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 Dynamic Cast If Else Chain -> Switch

Consider the following:

struct B { };

template<typename T>
struct D : B
{
    T t;
}

void g(int i) { ... }
void g(string s) { ... }
void g(char c) { ... }

void f(B* b)
{
    if (dynamic_cast<D<int>*>(b))
    {
        g(dynamic_cast<D<int>*>(b)->t);
    }
    else if (dynamic_cast<D<string>*>(b))
    {
        g(dynamic_cast<D<string>*>(b)->t);
    }
    else if (dynamic_cast<D<char>*>(b))
    {
        g(dynamic_cast<D<char>*>(c)->t)
    }
    else
        throw error;
};

Here there are only three possible types of T - int, string, char - but if the list of possible types were longer, say n, the if else chain would take O(n) to execute.

One way to deal with this would be to store an extra type code in D somehow and then switch on the type code.

The RTTI system must already have such a code. Is there someway to get access to it and switch on it?

Or is there a better way to do what I'm trying to do?

like image 621
Andrew Tomazos Avatar asked Dec 24 '12 03:12

Andrew Tomazos


People also ask

What is difference between Static_cast and dynamic_cast?

static_cast − This is used for the normal/ordinary type conversion. This is also the cast responsible for implicit type coersion and can also be called explicitly. You should use it in cases like converting float to int, char to int, etc. dynamic_cast −This cast is used for handling polymorphism.

What does dynamic cast do?

The dynamic type cast converts a pointer (or reference) to one class T1 into a pointer (reference) to another class T2 . T1 and T2 must be part of the same hierarchy, the classes must be accessible (via public derivation), and the conversion must not be ambiguous.

What is the use of dynamic cast operator in C++?

The primary purpose for the dynamic_cast operator is to perform type-safe downcasts. A downcast is the conversion of a pointer or reference to a class A to a pointer or reference to a class B , where class A is a base class of B .

Does dynamic_cast throw?

dynamic_cast will no longer throw an exception when type-id is an interior pointer to a value type, with the cast failing at runtime. The cast will now return the 0 pointer value instead of throwing.


2 Answers

C++11 is almost there.

In C++03 it was impossible because the only way to get a compile-time constant (which case requires) was through the type system. Since typeid always returns the same type, it couldn't produce different alternatives for switch.

C++11 adds constexpr and type_info::hash_code as a unique identifier of types, but doesn't combine them. You can use typeid in a constant expression on a of type name or statically-typed expressions, but because hash_code is a non- constexpr function you cannot call it.

Of course there are various workarounds, one of which you describe, and the most general of which apply a visitor over a type vector using template metaprogramming.

like image 157
Potatoswatter Avatar answered Sep 24 '22 02:09

Potatoswatter


Since only a few types are valid, you could solve this with virtual functions and template specialization instead:

struct B
{
    virtual void g() = 0;
}

template<typename T>
struct D : public B
{
    T t;
};

template<>
struct D<int> : public B
{
    int t;
    void g() { /* do something here */ }
};

template<>
struct D<std::string> : public B
{
    std::string t;
    void g() { /* do something here */ }
};

template<>
struct D<char> : public B
{
    char t;
    void g() { /* do something here */ }
};

void f(B* b)
{
    b->g();
}

This will fail at compile-time if you provide the wrong types, instead or requiring runtime checks (which C++ is quite bad at).

like image 44
Some programmer dude Avatar answered Sep 21 '22 02:09

Some programmer dude