免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: windoze

[C++] 前两天有人提到C++没反射,写了个实验版 [复制链接]

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
发表于 2015-10-27 17:21 |显示全部楼层
本帖最后由 windoze 于 2015-10-27 17:25 编辑

回复 10# yulihua49

C++的模板参数不光可以是type,也可以是编译期常数,所有字面常量和constexpr常量都可以拿来做模板参数。

之前说variant的动态性在read的过程中体现的更明显,假如有一组针对基本类型的输入操作:

  1. Src &operator>>(Src&src, int &v) {...}
  2. Src &operator>>(Src&src, std::string &v) {...}
  3. Src &operator>>(Src&src, double &v) {...}
  4. ...
复制代码
那么就可以用和上面说到的write过程很类似的手段去read一个variant,具体代码可以参见variant_reader
把variant读进来之后就可用variant::get<type>将其转化为具体的类型,如果variant中的实际类型和要求的类型不符就会抛出bad_get异常。

比如说有一个DBField类型,大致的实现会是这样的:

  1. DBField &operator>>(DBField&src, int &v) {
  2.     v=src.getInt();
  3.     return src;
  4. }
  5. DBField &operator>>(DBField&src, std::string &v) {
  6.     v=src.getString();
  7.     return src;
  8. }
  9. ...
复制代码
然后你就可以写:

  1. template<size_t I, size_t N> struct DBRecord_reader {
  2.     typedef typename cxl::to_variant<T>::type variant_type;
  3.     template<typename T> void operator(DBRecord &rec, T &t){
  4.         variant_type v;
  5.         rec.getField(I) >> v;
  6.         get<std::tuple_element<I, T>::type>()=v.get<std::tuple_element<I, T>::type>();
  7.         DBRecord_reader<I+1, cxl::tuple_size<T>::value>()(rec, t);
  8.     }
  9. };
  10. template<size_t N> struct DBRecord_reader<N, N> {
  11.     template<typename T> void operator(DBRecord &rec, T &t){}
  12. };
  13. template<typename ...T>
  14. void Read_DBRecord(DBRecord &rec, T &t) {
  15.     DBRecord_reader<0, cxl::tuple_size<T>::value>()(rec, t);
  16. }
复制代码
有了这一组针对基本类型的操作,你就可以动态处理任意的数据库记录,比如:

  1. typedef std::tuple<int, std::string ...> Your_Type;
  2. std::vector<Your_Type> vec;
  3. Connection conn=getConnection(...);
  4. ResultSet rs=conn.execute("SELECT ...");
  5. for(auto &&rec: rs) {
  6.     Your_type x;
  7.     Read_DBRecord(rec, x);
  8.     vec.push_back(std::move(x));
  9. }
复制代码
上述代码可以把任意数据库的内容读进任意tuple里,不需要针对每种tuple定义什么东西。

但是这里有一个小问题,tuple可以用模板元编程技术遍历,但标准的struct/class不支持这种技术,所以我写的反射库的主要功能就是把一个struct/class映射成一个tuple,然后上述的代码就可以应用于这些struct,在这个过程中你不需要单独把struct和一个特定的数据库表映射起来,只需要把struct和一个tuple映射起来,就可以支持任意数据库表,同时还可以支持JSON/XML/CSV这些东西。

论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
发表于 2015-10-28 09:13 |显示全部楼层
回复 10# yulihua49

g++ -Wall -fexceptions -march=core2 -O3 -std=c++11  -c /cpp/echo_server/main.cpp -o obj/Release/main.o


测试 一下就OK   g++带参数   -std=c++11

   

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2015-11-05 18:20 |显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2015-11-06 12:31 |显示全部楼层
本帖最后由 yulihua49 于 2015-11-06 12:44 编辑
BetonArmEE 发表于 2015-11-05 18:20
你们玩的太高端了,我还是用我的DirectStruct写个IDL文件 自动生成json和c结构之间转换函数 吧

你那个也是可以的,把连接贴出来吧。
只是,如果写sqlldr那样的程序怎么办呢?
运行时提供表名和相应的数据怎么处理呢?

我这样的程序:
unldasc tabname -W“where 。。。。” >tabname.txt
任意表卸载数据。

ldasc tabname <tabname.txt
加载任何表的数据。

你们的方案能弄出来吗?

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2015-11-06 12:47 |显示全部楼层
windoze 发表于 2015-10-26 17:08
回复 7# yulihua49

你的理解有误,尽管“类型”可以有任意多个,但这些“类型”并不是凭空生成的,每个 ...

存储模板可以用tuple,也可以用其他的。我就是用结构数组。有人用XML或JSON。
关键是你怎么处理模板。

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
发表于 2015-11-06 14:05 |显示全部楼层
回复 15# yulihua49

你这里说的“模板”不是C++的template吧……

用struct的问题就是struct不能按照下标访问成员,用XML/JSON当然也可以,但是你只能在运行时检查它们的元素,用tuple的话很多工作可以放在编译期。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2015-11-06 16:01 |显示全部楼层
本帖最后由 yulihua49 于 2015-11-06 16:06 编辑
windoze 发表于 2015-11-06 14:05
回复 15# yulihua49

你这里说的“模板”不是C++的template吧……

不是C++的template.是描述struct的template。
编译期处理,如何完成上面的题目:
运行时知道表名,处理他的数据。最简单的,加载卸载。

我们许多业务到运行期才知道数据和他们所在的表。
运行时可使用XML和JSON提供数据。解析后知道了表名和列名。
然后呢,怎么生成语句,怎么绑定变量,尤其是数组绑定。字符流无法实现数组绑定。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2015-11-06 20:33 |显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
发表于 2015-11-06 22:35 |显示全部楼层
支持创新, 呵呵呵呵, 牛人的技术实力是强啊...

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2015-11-06 23:04 |显示全部楼层
本帖最后由 yulihua49 于 2015-11-06 23:22 编辑
BetonArmEE 发表于 2015-11-06 20:33
回复 14# yulihua49

不是没有这个需求,而是因为难以实现而不敢提这个需求。
可是,现在,它并不难实现。

在一些分布系统里,一个节点要使用几十个参数表,那么它就要向服务器提起几十个功能调用。现在,只有一个功能调用就可以了。你提出表名,我给你数据。
这个功能调用,代码很短,并没有复杂的分析处理,调用泛型函数即可。注意,不是泛型宏。
尽管是运行时处理,效率也是极高的,比大多数手写的专用功能的性能要高的多。

你当然也可以说,没这个需求,写几十个服务调用好了。
但是,如果数据结构改变了,或增加了一些表,那么,你改造系统好了。

柔性编程,对应与制造业的柔性生产。就是在数据结构变化时,程序可以不变或少变。它的基础就是运行时泛型。
改变数据结构,是一个生产系统常见的业务升级。犹如电信系统层出不穷的套餐设计,推出一种新的套餐就要修改程序吗?
软件之所以软,就是善变。不善变,就是“软件不软”。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP