免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: OwnWaterloo
打印 上一主题 下一主题

[C++] 名字空间、重载候选与lambda。。。 这是g++的bug吗。。。 [复制链接]

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
1 [报告]
发表于 2016-01-05 17:42 |显示全部楼层
@OwnWaterloo太过分了,下次发帖的时候上微信跟我说一声啊,这问题我知道。

首先,我没看标准,所以这是不是bug我不知道,但是,从实现的角度上来说,按照旧的标准解释,这个行为是合理的。

为什么呢?这就需要看闭包到底是什么了。闭包是一个对象,确切的说,是一个函数对象(Functor),也就是说,闭包实际上是一个匿名的,实现了operator()的一个struct的一个实例而已,问题就在于这个实例是在哪儿声明的。

你using 了::ns::f,那么这两个函数都参与了重载,这个OK,然后,你调用了::ns::f([]{}),那么,ns::f这个模版关于这个匿名类的对应实例被特化出来了,然后调用了f(0),则int ::f(int)被特化出来了。现在问题是第三个调用了。

假设C++11对目前的ADL规则没有打补丁,那么,如果存在int ::f(main()::lambda());这样一个函数,那么它显然会参与重载决策,而::ns::f又被特化出来了,那必然会导致重载失败。

现在问题就成了“当我通过使用的方式特化某个函数时,编译器有没有权力自行特化其他函数”,貌似这个权力是有的(吧?)

这里的问题在于,首先lambda是函数对象,其次这个对象声明在main()作用域,然后就算using了::ns::f,f仍然在作用域,如果曾经特化过f的某个版本,而根据ADT肯定能找到::f(::f是main()的上层),那么重载失败就是可能的。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
2 [报告]
发表于 2016-01-05 17:44 |显示全部楼层
本帖最后由 starwing83 于 2016-01-05 17:44 编辑

可能都不需要ADL了,根本两个都是可见的,只要针对main()::lambda()类型的f被特化,就肯定会出现这个错儿,你自己试一下在clang里面手动特化某个模版看看还能不能编译过。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
3 [报告]
发表于 2016-01-21 13:13 |显示全部楼层
回复 22# OwnWaterloo


    虽然我是纯C控,但是作为世界上最复杂的编程语言,我就算不用,也得研究研究更新一下知识库嘛。

嗯,本质上是一类问题。我不知道对于模版的实例化有没有什么标准的规定,我建议你查一下(关于模版何时可以实例化的问题)。而且,函数模版在没有实例化的时候是否参与ADL也有关系的,万一是个Unspecified啥的估计就不是Bug了。

你只需要把lambda当作匿名结构体处理就OK了,这里跟lambda关系不大,主要还是函数模版实例化和函数重载选择的问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP