An open API service indexing awesome lists of open source software.

https://github.com/eyalz800/type_info

Cool C++ single header type info implementation for fun and profit.
https://github.com/eyalz800/type_info

header-only rtti standard type-information

Last synced: 3 months ago
JSON representation

Cool C++ single header type info implementation for fun and profit.

Awesome Lists containing this project

README

        

type_info
=========

Cool C++ Single-Header Type Info Implementation For Fun and Profit

Abstract
--------
It is not uncommon to encounter C++ projects with turned off RTTI.
In general, turning RTTI off is non-standard, however, sometimes reality makes us
give up RTTI knowingly.

In most cases, a choice to disable RTTI is made because it conflicts
with the main C++ idea of "You only pay for what you use.", since RTTI is added to every
polymorphic type, whether or not it is ever used.

Motivation
----------
Provide a simple solution using standard C++, implementing most of the
functionality given by the built in C++ RTTI implementation, for RTTI disabled projects,
in a way that generates extra information for a class on demand, per the user's request.

Contents
--------

* Enables dynamic casting using `dyn_cast(Source)` similar to dynamic_cast.
* Generates unique id for every type using `type_id()`.
* Obtain the type id of the dynamic type of an object using `type_id(Expression)`.
* Sibling casts are supported.
* Casts from a virtual base to derived are supported.

Example
-------

```cpp
#include "type_info.h"

void foo()
{
class a
{
public:
using zpp_bases = zpp::make_zpp_bases<>;
virtual zpp::dynamic_type zpp_dynamic_type() const { return *this; }
virtual ~a() = default;

private:
int value = 0x11111111;
};

class b
{
public:
using zpp_bases = zpp::make_zpp_bases<>;
virtual zpp::dynamic_type zpp_dynamic_type() const { return *this; }
virtual ~b() = default;

private:
int value = 0x22222222;
};

class c : public a, public b
{
public:
using zpp_bases = zpp::make_zpp_bases;
virtual zpp::dynamic_type zpp_dynamic_type() const override { return *this; }
virtual ~c() = default;

private:
int value = 0x33333333;
};

auto object = std::make_unique();
c * pc = object.get();
a * pa = pc;
b * pb = pc;

auto dyn_a_from_b = zpp::dyn_cast(pb);
auto dyn_b_from_a = zpp::dyn_cast(pa);
auto dyn_c_from_a = zpp::dyn_cast(pa);
auto dyn_c_from_b = zpp::dyn_cast(pb);

auto dyn_void_from_a = zpp::dyn_cast(pa);
auto dyn_void_from_b = zpp::dyn_cast(pb);
auto dyn_void_from_c = zpp::dyn_cast(pc);

std::cout << "a: " << pa << ", dyn_a_from_b: " << dyn_a_from_b << '\n';
std::cout << "b: " << pb << ", dyn_b_from_a: " << dyn_b_from_a << '\n';
std::cout << "c: " << pc << ", dyn_c_from_a: " << dyn_c_from_a << '\n';
std::cout << "c: " << pc << ", dyn_c_from_b: " << dyn_c_from_b << '\n';

std::cout << "a: " << pa << ", dyn_void_from_a: " << dyn_void_from_a << '\n';
std::cout << "b: " << pb << ", dyn_void_from_b: " << dyn_void_from_b << '\n';
std::cout << "c: " << pc << ", dyn_void_from_c: " << dyn_void_from_c << '\n';

std::cout << "type_id(): " << zpp::type_id() << '\n';
std::cout << "type_id(): " << zpp::type_id() << '\n';
std::cout << "type_id(): " << zpp::type_id() << '\n';

std::cout << "type_id(*pa): " << zpp::type_id(*pa) << '\n';
std::cout << "type_id(*pb): " << zpp::type_id(*pb) << '\n';
std::cout << "type_id(*pc): " << zpp::type_id(*pc) << '\n';
}
```

Disclaimer
----------
1. Performance of virtual base to derived and cross casts have a significant performance impact in comparison
to simple down casts. There is much room for optimization however, feel free to share your implementation.
2. Almost no tests were performed.
3. Inaccessible base classes do not work in the current implementation, however it is fairly easy to implement.
4. I did not implement dynamic cast for reference types, this is also left as a challenge to the reader.
5. The current implementation does not attempt to deal with the case where
the dynamic type of the object has two base class subobjects of the same type. The solution may be simple,
but involves substantial performance impact.

Final Words
-----------
I have implemented this utility mostly for fun, I did not measure whether it is better or worse than the
built in C++ RTTI.

I imagine some projects with turned off RTTI can use this on a small subset of their types
without having their entire project configured for RTTI.

Feel free to report issues or submit your own improvements via pull requests.