原文
以前的编译期反射
,大多需要写一个助手宏或额外的代码
去实现,比如iguana
就是如此,iguana
中需要这样定义一个结构
才能实现编译期反射
:
struct simple {int color;int id;std::string str;int age;
};
REFLECTION(simple, color, id, str, age);
虽然这是非侵入式
的,但是字段多了,写该宏
也是很麻烦的
,能不能去掉该宏
?
现在可愉快的声明:在C++20
中终于可去掉该宏
了!
yalantinglibs.reflection
库已实现了无需宏和非侵入式
的编译期反射函数
,让来看看雅兰亭库
的编译期反射库
的用法吧.
struct simple {int color;int id;std::string str;int age;
};using namespace ylt::reflection;int main() {simple p{.color = 2, .id = 10, .str = "hello reflection", .age = 6};//编译期取结构所字段个数static_assert(members_count_v<simple> == 4);//编译期取结构所有字段名的数组constexpr auto arr = get_member_names<simple>();//根据编译期索引取值CHECK(std::get<3> == 6); //`取年龄`CHECK(std::get<2> == "hello reflection"); //取串//根据运行期索引取值size_t index = 3;auto var = get(p, index);CHECK(*std::get<3>(var) == 6);//或`visit`访问std::visit([](auto field_value_ptr) {std::cout << *field_value_ptr << "\n";},var);//遍历结构取得字段值和字段名for_each(p, [](auto& field_value, auto field_name) {std::cout << field_value << ", " << field_name << "\n";});//遍历结构取得字段值,字段名和索引for_each(p, [](auto& field_value, auto field_name, size_t index) {std::cout << field_value << ", " << field_name << "\n";});
}
现在对简单
结构,不需要写额外的代码
就可实现编译期反射
了,比如编译期取字段个数,字段名,根据索引取字段值,遍历结构,取字段值,字段名和索引
.
酷不酷?
你以为就这些了吗,不,还有一些很酷
的没展示:比如根据字段名字取字段值,根据字段名字取字段索引,根据字段索引取字段名字
.
//编译期根据字段名取字段值auto& age2 = get<"age"_ylts>(p);CHECK(age2 == 6);auto& var1 = get<"str"_ylts>(p);CHECK(var1 == "hello reflection");//运行期根据字段名取字段值std::string field_name = "str";auto var2 = get(p, field_name);CHECK(*std::get<2>(var2) == "hello reflection");std::visit([](auto ptr) {std::cout << *ptr << "\n";},var2);//根据编译期索引取字段名constexpr std::string_view name1 = name_of<simple, 2>();CHECK(name1 == "str");//根据运行期索引取字段名size_t index = 2;constexpr std::string_view name2 = name_of<simple>(index);CHECK(name2 == "str");//根据编译期字段名取字段索引constexpr size_t idx = index_of<simple, "str"_ylts>();CHECK(idx == 2);constexpr size_t idx1 = index_of<simple>("str");CHECK(idx1 == 2);// 根据运行期字段名取字段索引std::string field_name = "str";size_t idx2 = index_of<simple>("str");CHECK(idx2 == 2);
除此外,还支持根据运行期字段的值
来取字段名和字段索引
:
int& age1 = p.age;size_t idx4 = index_of(p, age1);CHECK(idx4 == 3);auto name3 = name_of(p, age1);CHECK(name3 == "age");
更多测试代码:这里
现在感觉
如何?是不是正是你需要的编译期反射库
呢?
后面json,xml,yaml,protobuf
都会基于yalantinglibs
的该反射库
重构,让用户摆脱宏
,代码也会写得更舒服
.