diff --git a/docs/typeid.md b/docs/typeid.md new file mode 100644 index 0000000..d642c27 --- /dev/null +++ b/docs/typeid.md @@ -0,0 +1,128 @@ +# <nr/typeid.hpp> + +The `` 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<>()`. + +## Example + +```cpp +#include +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); +public: + 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(base); + + // Side-cast from InterfaceA. + InterfaceB* b = nr::type_cast(a); + + // Up-cast from InterfaceB. + Impl* i = nr::type_cast(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()` + +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 + +```cpp +std::cout << nr::type_id() << 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. + +_Example_ + +```cpp +class SomeType : public virtual BaseClass1, virtual BaseClass2 { + NR_TYPEID(SomeType, 8, BaseClass1, BaseClass2); +public: + // ... +}; +``` + +### `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(T*)` + +Alternative to `dynamic_cast()`. Can only be used with types that implement +the `NR_TYPEID()` macro. Supports casts in all directions (up, down and side). + +```cpp +BaseClass1* impl = get_some_implementation(); +BaseClass2* b2 = nr::type_cast(impl); +if (b2) { + // ... +} +SomeType* st = nr::type_cast(impl); +if (st) { + // ... +} +``` + +### `nr::type_adapter` + +A class that applies `nr::type_cast()` 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. + +```cpp +bool myfunction(nr::type_adapter impl) { + if (!impl) return false; + impl->do_stuff(); + return true; +} +```