- 论坛徽章:
- 44
|
本帖最后由 windoze 于 2015-10-26 00:34 编辑
C++的确没反射,我一开始搞了一个code generator,后来发现这么搞对于build system实在影响太大,所以后来我干脆转去用宏了。
代码在 https://github.com/windoze/cxl
这是一个header only库,大概这么用:
如果你有一个struct SC
- struct SC {
- int m1;
- const double m2;
- SC(int mm1, double mm2, int mm3) : m1(mm1), m2(mm2), m3(mm3) {}
- int get_m3() const { return m3; }
- void set_m3(int x) { m3 = x; }
- int get_m4() const { return 100; }
- private:
- int m3;
- };
复制代码 在外面定义几个宏:
- CXL_EXT_BEGIN_REFLECTED(SC, 4)
- CXL_REFLECTED_MEMBER(0, m1)
- CXL_REFLECTED_MEMBER(1, m2, CXL_SQL_FIELD("field2"))
- CXL_REFLECTED_ATTRIBUTE(2, int, m3, CXL_MEM_GETTER(get_m3), CXL_MEM_SETTER(set_m3))
- CXL_REFLECTED_RO_ATTRIBUTE(3, int, m4, CXL_MEM_GETTER(get_m4))
- CXL_EXT_END_REFLECTED()
复制代码 然后这个struct SC就可以支持反射了,比如你可以动态读写field:
- SC sc(10, 5.5, 84);
- cxl::set(0, sc, 42);
- assert(sc.m1==42);
- assert(cxl::get<int>(0, sc)==42);
复制代码 如果,field不能写或不能用你提供的类型读写,则会在运行时抛出std::bad_cast,而不是编译错误,比如:
- try {
- cxl::set(1, sc, 7.5);
- cxl::get<std::string>(0, sc);
- assert(false);
- } catch(std::bad_cast&) {
- }
复制代码 你还可以访问每个字段的一些metadata,目前预定义的有name, key, sql_table, sql_field, json_key, xml_node, xml_namespace, csv_field, 如要扩展可以在cxl/reflection/reflection_impl.hpp里加,三句话就行。
这些metadata可以用来干一些有用的事,比如:
- // 玩具SQL生成器
- std::string keys;
- for(size_t i=0; i<cxl::tuple_size<SC>::value; i++) {
- if(!keys.empty()) keys+=", ";
- keys+=get_element_sql_field<SC>(i);
- }
- keys = "SELECT " + keys + " FROM " + cxl::get_sql_table<SC>() + " WHERE "
- + cxl::get_element_sql_field<SC>(0) + "=?";
- assert(keys == "SELECT m1, field2, m3, m4 FROM SC WHERE m1=?");
复制代码 |
评分
-
查看全部评分
|