3

我一直在阅读 Josuttis 模板书,并且一直在尝试将头放在 ADL 上。他说“ADL 通过在命名空间和类中查找名称来“与”调用参数的类型“相关联”。我只是想看看它是如何在班级中查找名称的。我在下面放了一个测试示例。我看到它如何在命名空间中查找名称。

class bryan_ns {
  public:
  class bryan {
    public:
      enum E { e1 };
      static void bryan_test() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
  };

  void f(bryan::E) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

void f(int)
{
  std::cout << "::f(int) called\n";
}


int main()
{
  f(bryan_ns::bryan::e1); // calls ::f(int)
}

但是,如果我将 bryan_ns 更改为这样的命名空间:

namespace bryan_ns {
  public:
  class bryan {
    public:
      enum E { e1 };
      static void bryan_test() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
  };

  void f(bryan::E) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

void f(int)
{
  std::cout << "::f(int) called\n";
}


int main()
{
  f(bryan_ns::bryan::e1); // calls bryan_ns::f(bryan::E)
}
4

2 回答 2

7

ADL 将查看类型的封闭命名空间,以及类型本身。最好的例子是在类型内部定义的友元函数:

namespace X {
class test {
   friend void f( test ) { std::cout << "test" << std::endl; }
};
}
int main() {
   X::test t;
   f( t );
}

调用f(t)将查找X::f其声明仅在 type中可用test。这是友元函数声明的一个鲜为人知的特性:它们声明一个命名空间级别的函数,但只在类型内部提供声明。验证此行为的简单测试:

namespace X {
   class test {
      friend void f( test );
   };
   //void f( test );          // [1]
}
void X::f( X::test ) {}       // [2]
int main() {
   X::test t;
   f(t);                      // [3]
}

[2] 中的定义将触发编译错误,因为您只能定义一个已经声明的函数,并且由于 [2] 在命名空间之外,X该定义不符合自我声明的目的(如果您定义一个函数位于它所在的命名空间内,那么定义也是一个声明,但在这种情况下不是)。如果我们取消注释 [1],错误就会消失。或者,如果我们注释 [2],代码将编译,表明对于 [3] 中的调用,ADL 已在类中找到声明。

于 2012-07-13T02:54:09.580 回答
0

在第一个例子中,bryan_ns::f是一个非静态成员函数。中的表达式main没有.->成员运算符,因此它显然不是成员函数调用,bryan_ns::f也不是可行的函数。

于 2012-07-13T00:18:22.067 回答