rtti
static &dynamic type information
class Base {
public:
   virtual ~Base();
   virtual void name();
};
class Derived1 : public Base;
class Derived2 : public Base;Base* pd1 = new Derived1;
Base* pd2 = new Derived2;
// static type Base
// dynamic type DerivedXdynamic_cast
rtti
static type (compile time)
decltype
auto
dynamic type (runtime)
dynamic dispatch
using t = decltype(pd1); // Base*
auto p2 = pd1; // Base*
Base* p = new Base();
// no indication of error
static_cast<Derived1*>(b);pd1()->name(); // Derived1::name
Base* bp = new Base();
dynamic_cast<Derived1*>(b); // nulp
assert(
    typeid(*pd1) == typeid(*pd2)
) // failstatic
dynamic
static_cast
typeid
#include <typeinfo> typeid(whatever) -> const std::type_info&
typeid(type)
typeid(expr_of_polymorphic_t)
typeid(expr_of_non_polym_t)
typeid(size_t)typeid(std::string("Hello"))auto p = new PolymorphicT;
typeid(*p);Compile time
Compile time
Runtime
typeid(*p)
PolymorphicT p{}; // 0 initialized
typeid(*p); // std::bad_typeidwhere p == nullptr
Runtime
throw std::bad_typeid
no UB
- of static storage duration
 - theoretically subsequent invocations on the same type could return different objects
 
std::type_info
namespace std {
    class type_info {
        type_info() = delete;
        type_info(type_info) = delete;
        type_info& operator=(type_info) = delete;
        virtual ~type_info();
        
        bool operator==(const type_info& rhs) const noexcept;
        // (operator!= synthesized since C++20)
        bool before(const type_info& rhs) const noexcept;
        std::size_t hash_code() const noexcept;
        const char* name() const noexcept;
    };
}std::type_info
namespace std {
    class type_info {
        type_info() = delete;
        type_info(type_info) = delete;
        type_info& operator=(type_info) = delete;
        virtual ~type_info();
        
        bool operator==(const type_info& rhs) const noexcept;
        // (operator!= synthesized since C++20)
        bool before(const type_info& rhs) const noexcept;
        std::size_t hash_code() const noexcept;
        const char* name() const noexcept;
    };
}void use(Base* p) {
    auto&& type = typeid(*p);
    if (type == typeid(Derived1)) {
        special_logic1();
    }
    else if (type == typeid(Derived2)) {
        special_logic2();
    }
    ...
}std::unordered_map<std::type_index, std::string> m;
m[typeid(double)] = "Doubles are red";
m[typeid(32LL)] = "Long longs are blue";
m[typeid(std::string)] = "And this is cool";
for (auto&& [idx, msg] : m) {
    std::cout << idx.name() << ": " << msg << '\n';
}std::type_info
std::unordered_map<std::type_index, std::string> m;
m[typeid(double)] = "Doubles are red";
m[typeid(32LL)] = "Long longs are blue";
m[typeid(std::string)] = "And this is cool";
for (auto&& [idx, msg] : m) {
    std::cout << idx.name() << ": " << msg << '\n';
}#include <typeinfo>
#include <typeindex>
std::type_index(typeid(whatevah));returns mangled name
getting names of types
types
std::type_info::name()
mangled name
readable name
typeid(std::string).name()
NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >
example under g++
getting names of types
types
getting names of types
types
constexpr auto name = typeid(int).name();
into the detailverse
D1*
B1*
...
...
VFTablePtr
struct B1 {
    ...
    virtual void foo() {}
};
struct D1 : B1 { ... };
struct B2 {
    ...
    virtual void bar() {}
}
struct D2 : D1, B2 { ... }...
...
D2*
B2*
VFTablePtr
top_offset = 0
typeinfo for D2
B1::foo
top_offset = -8
typeinfo for D2
B2::bar
D1
B1
D2
B2
...
...
mangled_name
typeinfo for D2
vtable for d2
d2
example under g++
Performance
Performance
Performance
Performance
under libstdc++ (g++) and libc++ (Clang)
Performance
Performance
Performance
Performance
std::type_info::operator==
std::type_info::hash_code
std::type_info::name
or
under libstdc++ (g++) and libc++ (Clang)
!defined(_LIBCPP_NONUNIQUE_RTTI_BIT)
__GXX_MERGED_TYPEINFO_NAMES == 0
libstdc++
otherwise
default
otherwise
libc++
default
non standard compliant
disabling rtti
-fno-rtti
/GR-
under G++, Clang and similar
under MSVC
inheritance and exceptions
class my_custom_error : public std::runtime_error {
private:
	std::string message;
public:
	my_custom_error(std::string msg) :
        message{std::move(msg)}
    {
    }
    
    my_custom_error& operator=(const my_custom_error& other)
    {
    	message = other.message;
    }
    
    const char* what() noexcept {
    	return message.c_str();
    }
};try {
	throw my_custom_error("woah!");
} catch (const std::exception& e) {
	std::cerr << e.what() << '\n';
}more than inheritance
std::variant<T1, T2, ..., TN>
- holds object of any of types
 
T1, T2, ..., TN
- 
	
index() 
- 
	
std::get<Index>(variant)
 
std::any
- holds object of any type
 
- 
	
type() 
- 
	
std::any_cast<Target>(any)
 
rtti
rtti
- <typeinfo>, typeid, std::type_info, std::bad_typeid
 - std::type_info::hash_code, std::type_index
 - std::type_info::name(), symbol (de)mangling
 - dynamic_cast, downcast, upcast, sidecast, std::bad_cast
 - std::variant, std::monostate, std::bad_variant_access
 - std::any, std::any_cast
 - union
 
RAII
inheritance
virtual
- 
	
constructor
 - 
	
member initializer list
 - 
	
destructor
 - 
	
default constructor
 - 
	
std::initializer_list
 - 
	
in-class initializer
 - 
	
copy ctor
 - 
	
cpy assign op
 - 
	
move ctor
 - 
	
mv assign op
 - 
	
default members
 - 
	
deleted members
 - 
	
rule of 0
 - 
	
rule of 3/5
 - 
	
smart-ptrs
 - 
	
converting constructor
 - 
	
explicit specifier
 
- 
	
is-a relation
 - 
	
has-a relation
 - 
	
public inheritance
 - 
	
protected members
 - 
	
using declaration
 - 
	
final specifier
 - 
	
private & protected inheritance
 - 
	
multiple inheritance
 - 
	
diamond problem
 - 
	
empty base optimization
 
- 
	
base method hiding problem (shadowing)
 - 
	
virtual methods
 - 
	
override specifier
 - 
	
dynamic type
- 
		
RTTI
 - 
		
dynamic_cast
 - 
		
typeid
 - 
		
vtables
 
 - 
		
 - 
	
by value passing problem (slicing)
 - 
	
pure virtual function
 - 
	
abstract class
 
misc
- 
	
friends
 - 
	
nested members
 - 
	
conversion operators
 - 
	
operator overloading
 - 
	
member pointers
 - 
	
unions
- 
		
std optional
 - 
		
std variant
 - 
		
std any
 
 - 
		
 
type ereasure
pimpl
enable shared from this with private inheritance
linkage and static (non-member) functions
Liskov substitution principle
function member ref qualification
constexpr virtual
virtual inheritance
aggregate, pod, literal type
implement class in cpp file
delegation to sister class
RTTI
By Jan Bielak
RTTI
- 1,023