免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 6458 | 回复: 13

[C++] Boost里面的any和variant很好玩。 [复制链接]

论坛徽章:
89
水瓶座
日期:2014-04-01 08:53:31天蝎座
日期:2014-04-01 08:53:53天秤座
日期:2014-04-01 08:54:02射手座
日期:2014-04-01 08:54:15子鼠
日期:2014-04-01 08:55:35辰龙
日期:2014-04-01 08:56:36未羊
日期:2014-04-01 08:56:27戌狗
日期:2014-04-01 08:56:13亥猪
日期:2014-04-01 08:56:02亥猪
日期:2014-04-08 08:38:58程序设计版块每日发帖之星
日期:2016-01-05 06:20:00程序设计版块每日发帖之星
日期:2016-01-07 06:20:00
发表于 2014-11-18 12:11 |显示全部楼层

不过似乎没啥用途。

论坛徽章:
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
发表于 2014-11-18 13:00 |显示全部楼层
回复 1# fender0107401

any可以拿来做异构容器,variant其实就是tagged union,都挺有用的。

论坛徽章:
323
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
发表于 2014-11-18 13:09 |显示全部楼层
只用过COM中的variant

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
发表于 2014-11-18 13:21 |显示全部楼层
不用也不会受影响,用了可以简化一些东西。

论坛徽章:
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
发表于 2014-11-19 10:27 |显示全部楼层
回复 4# linux_c_py_php

如果你有这样的代码

  1. struct var {
  2.     int tag;
  3.     union {
  4.         int int_value;
  5.         double double_value;
  6.     };
  7. }

  8. switch(x.tag) {
  9. case INTEGER:
  10.     // do something with x.int_value
  11.     break;
  12. case DOUBLE:
  13.     // do something with x.double_value
  14.     break;
  15. default:
  16.     // unknown tag
  17. };
复制代码
可以用boost.variant简化成这样:

  1. typedef boost::variant<int, double> var;
  2. struct something_visitor : public boost::static_visitor<> {
  3.     void operator()(int int_value) { /* do something with int_value */ }
  4.     void operator()(double double_value) { /* do something with double_value */ }
  5.     template<typename T> void operator()(T t) { /* unknown type */ }
  6. };
  7. boost::apply_visitor(something_visitor(), x);
复制代码
代码好看一些

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2014-11-20 19:43 |显示全部楼层
windoze 发表于 2014-11-19 10:27
回复 4# linux_c_py_php

如果你有这样的代码可以用boost.variant简化成这样:代码好看一些


Isn't this a simple multi-overloader?

  1. template< typename Arg, typename ... Args >
  2. struct overloader : Arg, overloader<Args...>
  3. {
  4.     overloader( Arg arg_, Args ... args_ ) : Arg(arg_), overloader<Args...>( args_... ) {}
  5. };
  6. template< typename Arg >
  7. struct overloader<Arg> : Arg
  8. {
  9.     overloader( Arg arg_ ) : Arg(arg_){}
  10. };
  11. template< typename ... Args >
  12. auto make_overloader( Args ... args_ )
  13. {
  14.    return overloader<Args...>{ args_... };
  15. }

  16. auto visitor = make_overloader( []( int i ) {...}, []( double d ){...} );
  17. int ix;
  18. double dx;
  19. visitor( ix );
  20. visitor( dx );
复制代码

论坛徽章:
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
发表于 2014-11-20 21:20 |显示全部楼层
回复 6# lost_templar

你这样只解决了overload,没解决union的问题。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2014-11-20 22:02 |显示全部楼层
windoze 发表于 2014-11-20 21:20
回复 6# lost_templar

你这样只解决了overload,没解决union的问题。


很少接触 union, 不知你举的例子中是什么样子的场景,非用 union 不可?

对 union 的认识还停留在节省内存之类的初级阶段,而我用来计算的机器有 128 G 内存,根本想不起用 union.

论坛徽章:
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
发表于 2014-11-20 22:12 |显示全部楼层
回复 8# lost_templar

我是说tagged union,也就是Algebraic data type,能存一组不同类型的数据,通过一个tag标记到底保存了什么类型。
这种东西其实经常能用到,比如说一个JSON value,就有可能是一个数字、字符串、数组或者一个map,你要实现这么个东西就需要一个类似的结构。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2014-11-20 22:36 |显示全部楼层
windoze 发表于 2014-11-20 22:12
回复 8# lost_templar

我是说tagged union,也就是Algebraic data type,能存一组不同类型的数据,通过一个tag标记到底保存了什么类型。
这种东西其实经常能用到,比如说一个JSON value,就有可能是一个数字、字符串、数组或者一个map,你要实现这么个东西就需要一个类似的结构。


如果让我存储一组不同类型的数据,我可能直接用一个 lambda 函数或 tuple 做容器,这样来做

  1. template<typename ... Args >
  2. auto container( Args ... args )
  3. {
  4.     return [=]( auto function ){ return function( args... ); };
  5. }
复制代码
加上前文的 overloader
  1. template< typename Arg, typename ... Args >
  2. struct overloader : Arg, overloader<Args...>
  3. {
  4.     overloader( Arg arg_, Args ... args_ ) : Arg(arg_), overloader<Args...>( args_... ) {}
  5. };
  6. template< typename Arg >
  7. struct overloader<Arg> : Arg
  8. {
  9.     overloader( Arg arg_ ) : Arg(arg_){}
  10. };
  11. template< typename ... Args >
  12. auto make_overloader( Args ... args_ )
  13. {
  14.    return overloader<Args...>{ args_... };
  15. }
复制代码
再加上一个 function mapper 来处理容器里边的数据

  1. template< typename F >
  2. auto function_mapper( F f )
  3. {
  4.     return [=]( auto ... args ){ return container( f(args)... ); };
  5. }
复制代码
这样一来,就可以直接存储不同类型的数据到一个 lambda 中去

  1. auto my_data = container( 1, 1.0, "data", true, 4.3 );
复制代码
然后针对存储的类型生成处理函数

  1. auto process = make_overloader( []( int i ){...}, []( double d){...}, [](bool b){...}, [](string s){...} );
复制代码
最后将这个函数应用到 lambda 容器上去

  1. my_data( function_mapper( process ) );
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP