You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3.4 KiB


The <NiklasRosenstein/typeid.hpp> header provides a manual alternative over RTTI and dynamic_cast<>(). It can be used in cases where RTTI is not available or unknown to be enabled. At the same time, nr::type_cast<>() addresses a common problem with side-casts which can be very troublesome when using dynamic_cast<>().


#include <NiklasRosenstein/typeid.hpp>
namespace nr = niklasrosenstein;

struct Base {
  NR_TYPEID(Base, 1);
struct InterfaceA : public virtual Base {
  NR_TYPEID(InterfaceA, 2);
  virtual std::string do_a_stuff() = 0;
struct InterfaceB : public virtual Base {
  NR_TYPEID(InterfaceB, 3);
  virtual std::string do_b_stuff() = 0;

class Impl : public virtual InterfaceA, virtual InterfaceB {
  NR_TYPEID(Impl, 4);
  virtual std::string do_a_stuff() override { return "A stuff"; }
  virtual std::string do_b_stuff() override { return "B stuff"; }
  std::string do_impl_stuff() { return "Impl Stuff"; }

Base* get_some_implementation() {
  return new Impl;

int main() {
  Base* base = get_some_implementation();

  // Up-cast from Base.
  InterfaceA* a = nr::type_cast<InterfaceA>(base);

  // Side-cast from InterfaceA.
  InterfaceB* b = nr::type_cast<InterfaceB>(a);

  // Up-cast from InterfaceB.
  Impl* i = nr::type_cast<Impl>(b);

  std::cout << a->do_a_stuff() << std::endl;
  std::cout << b->do_b_stuff() << std::endl;
  std::cout << i->do_impl_stuff() << std::endl;

  del base;



This template overloads the ID for a specific type and can be used to retrieve the ID of a type that implements the NR_TYPEID() macro or for which NR_TYPEID_EX() has been declared

std::cout << nr::type_id<SomeType>() << std::endl;

NR_TYPEID(cls, id, ...)

This macro makes a class compatible to the type casting system provided with this lirbary. It assigns a type_id member and creates two functions named __virtual_cast() and __nonvirtual_cast() as well as some required friend declarations to allow the macro be placed in the private section.

Parameter Description
cls The name of the class for which the type ID is implemented.
id An unsigned integer ID that uniquely identifies the type in its valid domain. Two different types may have the same type ID if they are never used in the same context.
... The base classes of cls. Can be empty.


class SomeType : public virtual BaseClass1, virtual BaseClass2 {
  NR_TYPEID(SomeType, 8, BaseClass1, BaseClass2);
  // ...

NR_TYPEID_EX(type, id)

Associate an external class with a type ID. This allows you to assign a type ID to a type that does not provide a type_id member.

nr::type_cast<R, T>(T*)

Alternative to dynamic_cast<R>(). Can only be used with types that implement the NR_TYPEID() macro. Supports casts in all directions (up, down and side).

BaseClass1* impl = get_some_implementation();
BaseClass2* b2 = nr::type_cast<BaseClass2>(impl);
if (b2) {
  // ...
SomeType* st = nr::type_cast<SomeType>(impl);
if (st) {
  // ...


A class that applies nr::type_cast<T>() on the pointer that it is passed. This class is a very convenient helper for function arguments that expect a class that implements a specific interface.

bool myfunction(nr::type_adapter<InterfaceA> impl) {
  if (!impl) return false;
  return true;