Konrad Eisele
Konrad Eisele

Reputation: 3194

Get C++ RTTI as enum for dispatch in switch statement

Is it possible to get an compiletime enum id from the C++ rtti type_info ? I want to use it in a switch statement for dispatching on a type without first going through a hash. Is there some standard way of doing this? In pseudocode something like:

#include <iostream>
#include <typeinfo>
#include <typeindex>
using namespace std;

struct base { virtual void f(void) = 0; };
struct a : public base { int v; void f(void) {}; };
struct b : public base { int v; void f(void) {}; };

void f(base *v) {

    switch(typeid(*v).hash_code()) {
        case comiletime_hash(typeid(a)):
            cout << "Is a\n";
        break;
        case comiletime_hash(typeid(b)):
            cout << "Is b\n";
        break;
    }
}

int main(int argc, char **argv) {

    a v0;
    b v1;
    f(&v0);
    f(&v1);

    return 0;
}

However hash_code is only available at runtime.

I want to find out weather I can use Rtti to rewrite some code from c:

  enum { typ1, typ2 ...}
  struct { int Tag; union { struct t1; struct t2;...}}
   ...
   switch (v->Tag) {
   case typ1: .... do something t1
   case typ2: ... do something t2
   ... }

I want to retain the switch statement. I'm not looking for a solution using dynamic_cast if-elseif cascade or a vitual functions.

Upvotes: 2

Views: 1742

Answers (2)

DartFNM
DartFNM

Reputation: 81

A little trick, how to create static information about types so that you can compare them quickly with one switch statically or dynamically in C++11.

#include <iostream>
#include <vector>

struct Base {
    int m_ClassID;
    Base(int _id) : m_ClassID(_id) {} // dynamic classID
};

template<int N>
struct Base_ : Base {
    static constexpr int g_ClassID = N; // static classID
    Base_() : Base(N) {}
};

struct A : Base_<2222> // define ClassID
{};

struct B  : Base_<3333> // define ClassID
{};

void DoForAnyBase(Base* pBase) {
    switch(pBase->m_ClassID) {
        case A::g_ClassID:
        printf("I'm A");
        break;
        case B::g_ClassID:
        printf("I'm B");
        break;
    }
}

int main() {
    std::vector< Base* > aTypes;
    aTypes.push_back( new A() );
    aTypes.push_back( new B() );

    for( Base* pCur : aTypes) {
        DoForAnyBase(pCur);
        delete pCur;
    }
}

Upvotes: 1

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136256

The compiler generates std::type_info for each type independently of other types. There is no unique compile-time enum/integer for each class.

You probably need to add another virtual function to your hierarchy that would obviate the need to use that switch statement at all. Or use visitor pattern.

Alternatively, try Open and Efficient Type Switch for C++.

Upvotes: 1

Related Questions