朋友的功能

时间:2010-12-09 08:51:02

标签: c++ lookup

以下是什么意思(特别是突出显示的部分)?为什么表达式'f(a)'被视为'演员表达'?

  

C ++ 03 $ 3.4。/ 3-“查找不合格的名称   用作a的后缀表达式   函数调用在3.4.2中描述。   [注:用于确定的目的   (在解析期间)是否是表达式   是函数的后缀表达式   调用,通常的名称查找规则   应用。 3.4.2中的规则没有   对句法解释的影响   一个表达。例如,

typedef int f;
struct A {
friend void f(A &);
operator int();
void g(A a) {
f(a);
}
};

表达式f(a)是等效于int(a)的强制转换表达式。因为表达式不是函数调用,所以参数依赖的名称查找(3.4.2)不适用,并且找不到友元函数f。 ]“

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

这意味着解析器首先确定括号前的表达式是 id 还是 postfix-expression 。在这种情况下,它会看到f,并且最接近的f定义为typedef int f - 因此它总结表达式被解释为int(a)并且不执行Koenig查找。

让我们拥有这段代码(您可以在线试用:http://ideone.com/clone/eRKvP

typedef int f;
namespace x {
  struct A {
    friend void f(A &);
    //friend void f(); // # 1
    operator int();
    void g(A a) {
      //void f();  // # 2
      (void)f(a); // # 3
    }
  };
}

如果您从f声明了一个(无关的)函数g,它将被解释为函数调用,Koenig查找将找到正确的重载(请参阅第#2行)。

f的朋友声明不应该适用于此,因为

  

11.4 / 1:......朋友的名字不属于班级范围,

然而,让我感到不安的是,取消注释#1会使编译器(在本例中为gcc)也调用x::f(A&)。不知道为什么会这样。 [在Comeau Online编译器中,它按预期工作(例如。#1不影响行#3)。但是,最新的测试版在编译此代码时遇到了问题。]

PS:如litb所述,C ++ 0x中的规则略有不同:

  

3.4.2 / 3:

     

设X是由...生成的查找集   unquali fi ed lookup(3.4.1)并让Y成为   参数生成的查找集   从属查找(定义如下)。   如果X包含

     
      
  • 类成员的声明,或
  •   
  • 块范围函数声明,它不是using声明或
  •   
  • 既不是函数也不是函数模板的声明
  •   
     

然后Y为空。否则Y就是   发现的一组声明   与

关联的名称空间

粗体项将使编译器仅考虑void f()并且因参数太多而失败。

似乎是由issue 218的决议引入的。