c++polymorphismdynamic-cast

Runtime std::conditional


I have polymorphic classes Base, Derived1 and Derived2.

I want to make

bool b = typeid(*base) == typeid(Derived1);

dynamic_cast<typename std::conditional<b, Derived1*, Derived2*>::type>(base)

My compiler says that b is not a compile time expression (and I understand what this means). Is there a way to solve the problem?


Solution

  • You do not need std::conditional here. As you are making a dynamic cast, this cast happens at runtime anyhow, so theres no point in trying to push it into compile time. Just remove std::conditional and the problem is gone:

    if (b) 
       dynamic_cast<Derived1*>(base)
    else 
       dynamic_cast<Derived2*>(base)
    

    Note that this code is as pseudo as yours and that chances are high that you do not need a cast in the first place. Maybe you do, but without context I guess that you rather need a virtual function.

    Moreover, bool b = typeid(*base) == typeid(Derived1); looks like you want to cast to Derived1* only when the cast would suceed. However, dynamic_cast does already tell you when a cast cannot be made by returning a nullptr.


    If you are looking for a way to "hide" the cast in a function, this isnt going to work. If you write a base* my_cast(auto* x) as you mention in a comment, it will always return a base* no matter what you cast inside the function:

    #include <iostream>
    #include <type_traits>
    
    struct base { 
        virtual ~base() {}
        void hello() { std::cout << "base\n";} // not virtual
    };
    
    struct derived : base {
        void hello() { std::cout << "derived\n";}
    };
    
    base* foo(auto* b) {
        auto d = dynamic_cast<derived*>(b);  // cast to derived  
        d->hello();
        return d;                            // and return
    }
    
    int main() {
        base b;
        auto x = foo(&b);
        std::cout << std::is_same<base*,decltype(x)>::value << "\n";
        std::cout << std::is_same<derived*,decltype(x)>::value << "\n";
        x->hello();
    }
    

    Output is:

    derived
    1
    0
    base