Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is RTTI needed for non-polymorphic typeid?

Tags:

c++

gcc

c++17

rtti

I have the following piece of code :

template<typename T>
class genericHandler{public: using evt_t = T;};

template<typename T>
class specialHandler : public genericHandler<T> {  /* more stuff */ };

int main(int argc, char *argv[]) {
    
    std::any any_var = specialHandler<int>{};
    
    auto f = [&any_var](auto evtHandler) {
        using EventType = typename std::remove_reference<decltype(evtHandler)>::type ::evt_t;
        if(any_var.type() == typeid(EventType)) { std::cout << "yes" << std::endl; } else { std::cout << "no" << std::endl; }
    };

    auto h = specialHandler<int>{ };
    f(h);
}

Try it on Coliru

When called, evtHandler is of non-polymorphic derived type specialHandler. According to cppreference, we have :

When applied to an expression of polymorphic type, evaluation of a typeid expression may involve runtime overhead (a virtual table lookup), otherwise typeid expression is resolved at compile time.

When I compile with gcc and -fno-rtti, I get the following error message :

cannot use 'typeid' with '-fno-rtti'

RTTI is run-time type information, which should not be needed in the case of non-polymorphic typeid that can be deduced at compile-time. Did I miss something ?

like image 483
Magix Avatar asked Jul 28 '20 11:07

Magix


1 Answers

You're asking two questions.

  1. RTTI is run-time type information, which should not be needed in the case of non-polymorphic typeid ...

    But this is a compiler switch, not a language feature, so you should check the compiler documentation:

    -fno-rtti

    Disable generation of information about every class with virtual functions for use by the C++ runtime type identification features (dynamic_cast and typeid). If you don't use those parts of the language, you can save some space by using this flag. Note that exception handling uses the same information, but it will generate it as needed. The dynamic_cast operator can still be used for casts that do not require runtime type information, i.e. casts to void * or to unambiguous base classes.

    (my emphasis).

    So the switch disables the entire typeinfo system to save space. If you want typeinfo (or you want to use a standard library facility that uses typeinfo), then don't explicitly disable typeinfo with a compiler option.

  2. ... non-polymorphic typeid that can be deduced at compile-time

    Edit, as Mr. Wakely points out, the issue is that you're explicitly using typeid in your own code.

    Although std::any may be capable of erasing the stored type from the top-level object without RTTI, this is implementation-dependent, and it definitely can't implement std::any::type() without using the typeid/typeinfo you told GCC not to generate.

Oh, and I forgot

  1. Did I miss something ?

    Yes, to ask your actual question, which is

    I'm erasing it because I need to solve a circular template dependency, sadly I am not free to 'simply not erase it' here. Do I have any alternative that doesn't use RTTI

    Sure, type erasure doesn't depend on RTTI.

    Only automated type erasure depends on RTTI and, as above, not all of that. You can either avoid std::any::type() or write your own discriminated union by hand - you'd need to enumerate your types, but only the enumeration itself needs to be visible to all users of the DU.

like image 142
Useless Avatar answered Nov 12 '22 17:11

Useless