Browse Source

add docs/

Niklas Rosenstein 3 years ago
No known key found for this signature in database GPG Key ID: 6D269B33D25F6C6
1 changed files with 128 additions and 0 deletions
  1. + 128
    - 0

+ 128
- 0

@ -0,0 +1,128 @@
# <nr/typeid.hpp>
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
## Example
#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;
## API
### `nr::type_id<T>()`
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) {
// ...
### `nr::type_adapter<T>`
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;