How can I add reflection to a C++ application?

前端 未结 28 1612
感动是毒
感动是毒 2020-11-21 11:25

I\'d like to be able to introspect a C++ class for its name, contents (i.e. members and their types) etc. I\'m talking native C++ here, not managed C++, which has reflection

28条回答
  •  终归单人心
    2020-11-21 11:52

    The RareCpp library makes for fairly easy and intuitive reflection - all field/type information is designed to either be available in arrays or to feel like array access. It's written for C++17 and works with Visual Studios, g++, and Clang. The library is header only, meaning you need only copy "Reflect.h" into your project to use it.

    Reflected structs or classes need the REFLECT macro, where you supply the name of the class you're reflecting and the names of the fields.

    class FuelTank {
        public:
            float capacity;
            float currentLevel;
            float tickMarks[2];
    
        REFLECT(FuelTank, capacity, currentLevel, tickMarks)
    };
    

    That's all there is, no additional code is needed to setup reflection. Optionally you can supply superclasses (in the parenthesis of the first argument) and field annotations (in the parenthesis preceeding the field you want to annotate) to be able to traverse superclasses or add additional compile-time information to a field (such as Json::Ignore).

    Looping through fields can be as simple as...

    for ( size_t i=0; i

    You can loop through an object instance to access field values (which you can read or modify) and field type information...

    FuelTank::Class::ForEachField(fuelTank, [&](auto & field, auto & value) {
        using Type = typename std::remove_reference::type;
        std::cout << TypeToStr() << " " << field.name << ": " << value << std::endl;
    });
    

    A JSON Library is built on top of RandomAccessReflection which auto identifies appropriate JSON output representations for reading or writing, and can recursively traverse any reflected fields, as well as arrays and STL containers.

    struct MyOtherObject { int myOtherInt; REFLECT(MyOtherObject, myOtherInt) };
    struct MyObject
    {
        int myInt;
        std::string myString;
        MyOtherObject myOtherObject;
        std::vector myIntCollection;
    
        REFLECT(MyObject, myInt, myString, myOtherObject, myIntCollection)
    };
    
    int main()
    {
        MyObject myObject = {};
        std::cout << "Enter MyObject:" << std::endl;
        std::cin >> Json::in(myObject);
        std::cout << std::endl << std::endl << "You entered:" << std::endl;
        std::cout << Json::pretty(myObject);
    }
    

    The above could be ran like so...

    Enter MyObject:
    {
      "myInt": 1337, "myString": "stringy", "myIntCollection": [2,4,6],
      "myOtherObject": {
        "myOtherInt": 9001
      }
    }
    
    
    You entered:
    {
      "myInt": 1337,
      "myString": "stringy",
      "myOtherObject": {
        "myOtherInt": 9001
      },
      "myIntCollection": [ 2, 4, 6 ]
    }
    

    See also...

    • Reflect Documentation
    • Reflect Implementation
    • More Usage Examples

提交回复
热议问题