我一直在阅读 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)
}

最佳答案

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 ,其声明仅在 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] 在 namespace X 之外,该定义不用于自我声明的目的(如果您在它所在的命名空间内定义一个函数,那么该定义也是一个声明,但在这种情况下不是)。如果我们取消注释 [1],错误就会消失。或者,如果我们注释 [2],则代码将编译,表明对于 [3] 中的调用,ADL 已在类中找到了声明。

关于c++ - 参数相关查找是否也只搜索 namespace 或类?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11462474/

10-11 22:53
查看更多