Skip to content

TheNitesWhoSay/RareCpp

Repository files navigation

RareCpp MIT License Header Only C++17 GCC 10.1 Clang 9.0.0 MSVC 19.26 644 Tests Passed

C++ Random Access Reflection & Extensions: adding a simple, intuitive means of reflection to C++


Documentation Home

Quick-Start Guide

Component Summary Examples
RareTs Reflection & type support link descrlink descrlink descrlink descr
RareBuilder Adaptive object builder link descrlink descrlink descrlink descr
RareMapper Dynamic type mapping link descrlink descrlink descrlink descr
RareJson Reflection-based JSON I/O link descrlink descrlink descrlink descr

Examples

Simple Example: Run

#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

JSON & Builders Example: Run

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): Run

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" }
  ]
}

More Examples / How to...

Features

Reflect

  • 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.

Annotate

  • 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

Member Information

  • 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

Access supers

  • In lambda loops
  • By constexpr index
  • By runtime index

Extensions

  • 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

Limitations

C++ Version

  • C++17 and up required

Supported Compilers

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)

Known Compiler Issues

  • 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

Known General Limitations

  • 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)

Documentation Home

Video Preview

RareCppPreview.webm