我希望能够自省一个c++类的名称,内容(即成员及其类型)等。这里我说的是原生c++,而不是托管c++,托管c++有反射。我意识到c++使用RTTI提供了一些有限的信息。哪些附加库(或其他技术)可以提供这些信息?


当前回答

RareCpp库实现了相当简单和直观的反射——所有字段/类型信息都被设计成可以在数组中使用,或者感觉像是数组访问。它是为c++ 17编写的,可与Visual Studios、g++和Clang一起使用。这个库只有头文件,这意味着你只需要将“Reflect.h”复制到你的项目中就可以使用它。

被反射的结构体或类需要REFLECT宏,在该宏中您可以提供所反射的类的名称和字段的名称。

class FuelTank {
    public:
        float capacity;
        float currentLevel;
        float tickMarks[2];

    REFLECT(FuelTank, capacity, currentLevel, tickMarks)
};

这就是全部内容,不需要额外的代码来设置反射。可选地,您可以提供类和字段注释,以便能够遍历超类或向字段添加额外的编译时信息(例如Json::Ignore)。

遍历字段可以简单到…

for ( size_t i=0; i<FuelTank::Class::TotalFields; i++ )
    std::cout << FuelTank::Class::Fields[i].name << std::endl;

您可以通过对象实例循环访问字段值(您可以读取或修改)和字段类型信息……

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

JSON库构建在RandomAccessReflection之上,它可以自动识别适当的JSON输出表示来读写,并且可以递归遍历任何反射字段,以及数组和STL容器。

struct MyOtherObject { int myOtherInt; REFLECT(MyOtherObject, myOtherInt) };
struct MyObject
{
    int myInt;
    std::string myString;
    MyOtherObject myOtherObject;
    std::vector<int> 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);
}

上面的代码可以这样运行……

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

参见……

反映文档 反映实现 更多用法示例

其他回答

你可以通过Boost::Hana库中的BOOST_HANA_DEFINE_STRUCT实现很酷的静态反射功能。 Hana非常通用,不仅适用于您所想到的用例,还适用于许多模板元编程。

在我的c++生涯中,我知道的两个类似反射的解决方案是:

1)使用RTTI,如果你能够从一个“对象”基类派生所有的类,它将为你提供一个引导来构建类似反射的行为。该类可以提供一些方法,如GetMethod, GetBaseClass等。至于这些方法是如何工作的,你需要手动添加一些宏来装饰你的类型,这些宏在幕后创建类型的元数据,为GetMethods等提供答案。

2)如果你可以访问编译器对象,另一个选择是使用DIA SDK。如果我没记错的话,这允许您打开pdbs,其中应该包含c++类型的元数据。也许足够做你想做的事了。例如,本页展示了如何获取类的所有基类型。

这两种解决方案都有点难看!没有什么比c++更能让你欣赏c#的奢华了。

祝你好运。

我建议使用Qt。

有一个开源许可证和一个商业许可证。

你可以在这里找到另一个库:http://www.garret.ru/cppreflection/docs/reflect.html 它支持两种方式:从调试信息中获取类型信息和让程序员提供该信息。

我也对反思我的项目感兴趣,发现了这个库,我还没有尝试过,但尝试了这个家伙的其他工具,我喜欢他们的工作方式:-)

当我想要在c++中进行反射时,我读了这篇文章并改进了我在那里看到的东西。对不起,没有罐头。结果不是我的…但你当然可以得到我所拥有的,然后从那里开始。

我目前正在研究,当我喜欢的时候,使用inherit_linear的方法使可反射类型的定义更容易。实际上我已经学了很多,但还有一段路要走。c++ 0x中的变化很可能在这方面有很大的帮助。