C++ Random Access Reflection & Extensions: adding a simple, intuitive means of reflection to C++
Component | Summary | Examples |
---|---|---|
RareTs | Reflection & type support | |
RareBuilder | Adaptive object builder | |
RareMapper | Dynamic type mapping | |
RareJson | Reflection-based JSON I/O |
#include <rarecpp/reflect.h>
#include <iostream>
struct MyObj
{
int a = 42;
float b = 1337.f;
REFLECT(MyObj, a, b)
};
int main()
{
MyObj myObj{};
RareTs::Members<MyObj>::forEach(myObj, [&](auto member, auto & value) {
std::cout << member.name << ": " << value << std::endl;
});
}
Output:
a: 42
b: 1337
struct Point
{
float x;
float y;
NOTE(hash, Json::Ignore) // Control behavior with member or class-level annotations!
size_t hash = 0;
REFLECT(Point, x, y, hash)
};
struct Descriptor
{
std::string name;
std::string address;
REFLECT(Descriptor, name, address)
};
struct Area
{
int id;
Descriptor descriptor;
std::vector<Point> points;
REFLECT(Area, id, descriptor, points)
};
int main()
{
auto area = RareBuilder<Area>()
.id(92)
.descriptor(RareBuilder<Descriptor>().name("some area").address("12345 main street").build())
.points({{1.1f, 2.2f}, {1.9f, 3.2f}, {1.3f, -2.5f}, {-4.2f, -1.2f}})
.build();
std::cout << Json::pretty(area) << std::endl;
}
Output:
{
"id": 92,
"descriptor": {
"name": "some area",
"address": "12345 main street"
},
"points": [
{"x": 1.1,"y": 2.2},
{"x": 1.9,"y": 3.2},
{"x": 1.3,"y": -2.5},
{"x": -4.2,"y": -1.2}
]
}
Auto-Reflection Example (requires C++20):
struct Item
{
int id = 0;
std::string name {};
};
struct Collection
{
std::string description {};
std::vector<Item> items {};
};
int main()
{
Collection collection { "my collection", {{0, "first"}, {1, "second"}} };
std::cout << Json::pretty(collection);
}
Output:
{
"description": "my collection",
"items": [
{ "id": 0, "name": "first" },
{ "id": 1, "name": "second" }
]
}
- REFLECT classes and up to 125 class members
- REFLECT from inside the class definition
- REFLECT from outside the class definition*
- REFLECT static & non-static members
- REFLECT data members
- REFLECT reference members
- REFLECT functions
- REFLECT overloaded-functions
- REFLECT super-classes
- REFLECT templated-classes
- REFLECT templated-members**
* Reflection from outside the class definition can be done on public and protected members - or - with more limitations than the in-class macro, on private members.
** Any members based on the class-level template parameters and any functions for which template parameters are inferred from parameters are reflectable, reflecting other templated members is not always possible.
- NOTE classes, members, super-classes and overloads to tag them with additional compile-time information
- NOTE using any data available in constexpr, user-defined or library-specific
- Common interface to check for note-of-type presence and get note values on particular members/classes/supers/overloads
- Common interface to filter and iterate notes on particular members/classes/supers/overloads
- Iterate members
- Access members by constexpr index
- Access members by runtime index
- Access members by name string
- Access members by identifier
- Get member static value, instance value, type, pointer type, name, index, staticness, access-protection modifier, offset, and overloads
- In lambda loops
- By constexpr index
- By runtime index
- Adaptive Structures (dynamically create structures consisting of one some combination/subset of one or more classes members)
- RareBuilder - Type-safe, adaptive-struct-based builder implementation
- RareMapper - Reflection-based object mapper
- RareJson - JSON I/O for reflected structures
- C++17 and up required
RareCpp minimizes use of compiler-specific features wherever possible, other compilers may work without modification and may or may not be possible to add to supported compilers upon request.
Use of compiler versions lower than preferred may disable or cause bugs with certain features.
- GCC Minimum: 10.1 (10.3.0 and up preferred)
- Clang Minimum: 9.0.0 (15.0.0 and up preferred)
- MSVC Minimum: 19.26 (MSVC 19.29/Visual Studios 2019 version 16.11.2 and up preferred)
- Unable to use the REFLECT macro in non-public sections in GCC versions before 12, recommended to use public sections for the REFLECT macro until GCC 12 has wider support & adoption
- MSVC 1932 (Visual Studio 2022 version 17.2.2) and up is required to accurately detect the access-protection level of protected members
- Cannot currently reflect type alias-members
- Cannot currently reflect the relationship between parent and nested classes (nested classes themselves can be reflected)
- Cannot currently detect the access-protection level of overloads (they will default to private)
- Cannot currently reflect all template members (cannot reflect templated data members not-based on class-level template parameters nor templated functions with parameters that can't be deduced from function parameters)