2.1. Reflection: REFLECT Macro - TheNitesWhoSay/RareCpp GitHub Wiki

REFLECT Macro

struct MyObj
{
    int a;
    int b;
    std::string c;

    REFLECT(MyObj, a, b, c)
};

The REFLECT macro takes the name of your object followed by the names of members you wish to reflect; you can supply anywhere from zero to 125 members in the REFLECT macro. Many different types of members can be reflected in this way, be they static or non-static, templated or regular, primitives, objects, pointers, references, functions and overloads.

The single instance of the REFLECT macro is all that's required to be able to use RareCpp to iterate or otherwise access the members of a given object (see Reflect Object); as well as to use many extensions.

Annotations / Notes

struct MyObj
{
    int a;

    NOTE(b, Json::Name{"beta"}, Json::Stringify)
    int b;

    NOTE(c, Json::Ignore)
    std::string c;

    REFLECT(MyObj, a, b, c)
};

Sometimes you may need to supply additional information about a member, such as to skip the member in certain operations or to name it something different in serialized data; in RareCpp this is done with the NOTE macro (an "annotation").

The NOTE macro takes the name of the thing to which you're attaching additional information, and whatever compile-time values you wish to supply; e.g. the above NOTEs say that the "b" field in Json should be named "beta" and the value should be quoted/stringified.

Class-Level Annotations

struct Parent {};

NOTE(Child, RareTs::Super<Parent>)
struct Child : Parent
{
    int a;
    int b;
    std::string c;

    REFLECT_NOTED(Child, a, b, c)
};

Classes may also have NOTEs ("class-level annotations") to supply additional information about the class type, for instance, the super-classes.

Whenever you have a class-level annotation you need to use the REFLECT_NOTED macro, the REFLECT_NOTED macro is exactly the same as the REFLECT macro except it signals that the class itself is reflected (member annotations do not affect which macro you should choose).

Reflect From Outside Class Bodies

There are two strategies for reflecting objects when you can't place a macro inside the body of the target struct/class, which is a very common situation with types with imported libraries: The proxy approach and private-reflect approach.

struct UnownedObject { int a; int b; };

template <> struct RareTs::Proxy<UnownedObject> : UnownedObject
{
    NOTE(a, "You can also place NOTE on members while proxying")

    REFLECT(RareTs::Proxy<UnownedObject>, a, b)
};

Placing the REFLECT macro in a specialization of RareTs::Proxy, which extends your type, cannot reflect private members, but otherwise works the same as in-class reflection with no added restrictions. Notes can be placed on members of your target class within the proxy, or on the proxy itself.

The private-reflect approach, done with the REFLECT_PRIVATE, REFLECT_PRIVATE_NOTED, or REFLECT_PRIVATE_EMPTY macros (which must be in the global scope) can reflect private members (as well as public and protected members), but comes with many limitations not shared by the in-class reflect macros, namely: references, overloads, and templated members canont be reflected, members offsets will not be provided, and templated structs/classes cannot be reflected. These forms of reflection do NOT involve casting/UB, rather they use the standard-legal private-member exfoliation trick.

struct UnownedObject { int a; int b; };

REFLECT_PRIVATE(UnownedObject, a, b)

If you need notes on the class type or any of the members, you need to instead use the REFLECT_PRIVATE_NOTED macro, which has a more complicated syntax:

struct UnownedObject { int a; int b; };

REFLECT_PRIVATE_NOTED(
	(UnownedObject) (RareTs::Buildable),
	(a) (Json::Name{"asdf"}, Json::Stringify),
	(b) ()
)

Finally if you have no members to reflect, but need to reflect a struct/class just to put a NOTE on it, you need to use the REFLECT_PRIVATE_EMPTY macro:

struct A {};
struct B : A {};

REFLECT_PRIVATE_EMPTY(B, RareTs::Super<A>, "more notes...")

Up Next...

  • Reflection Interfaces - teaches how to access information about reflected classes/supers/members
  • Notes - teaches more about working with notes
⚠️ **GitHub.com Fallback** ⚠️