C++中一个名字查找的小知识

最近看C++标准中的3.4 name lookup章节,碰巧的是stackoverflow也有人提问,他们对这个问题很疑惑,回答的也并不好。
https://stackoverflow.com/questions/25672745/friend-declarations-is-this-a-bug-in-clang

其中C++标准中$3.4.1章节有一个例子:

typedef int f;
namespace N {
     struct A {
        friend void f(A &);
        operator int();
        void g(A a) {
            int i = f(a);
            // f is the typedef, not the friend
            // function: equivalent to int(a)
        }
    };
}

标准上的注解的意思是f最终是一个typedef, 不会使用friend void f(A&)这个函数。

我自己的理解是:

  1. 在类中声明的friend函数在普通查找中,是不可见的,除非在类声明之前有正式的声明,也就是说friend声明不能代替正式的声明,这是标准所规定的。既然是不可见的,就不会hide掉那个typedef的f。标准$3.3.10讲的name hiding在这里不起作用。
  2. 名字查找要是从普通查找开始的,普通查找就是从内到外一层层地找,找到一个名字,立马停止。在这里找到了f是typedef。普通查找完成后才有ADL查找。
  3. 因为2找到的是typedef,不是一个函数,所以ADL不会介入。ADL是C++11的新规则。如果函数调用是非限定的,例如不是: 某namespace::f(a), 某class::f(a), object_ptr->f(a), 或者object.f(a)之类的调用,并且参数是用户定义类型,就会发起ADL,它把函数调用中的参数所属的namespace也拉进来找这个函数f。所以ADL介入的条件是要么普通查找找不到这个名字或者找到了而且确实是个函数,那么就把参数所属的namespace也拉进来找,最后凑成一个函数集合,做重载解析规则选出最合适的函数。
    在这个例子中如果把typedef int f改成 int f()就会发生ADL。普通查找首先会找到int f(),因为是函数,所以用ADL继续找,找到void f(A&),编译器会说"error: void value not ignored as it ought to be"。

这是由于ADL能找到只声明为friend而没有正式声明的函数,标准就是这么规定。并且void f(A&)比int f()更合适,但是void赋值给 i肯定出错,所以编译器报错啦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值