在没有限定条件的命名空间中调用函数

时间:2017-03-07 13:40:11

标签: c++ c++11 namespaces

查看boost::polygon的源代码,我看到了以下主题的许多应用程序:

#include <iostream>

namespace B {

struct A {
  void foo() const { std::cout << "foo" << std::endl; }
};

void bar(const A &a) { a.foo(); }
void baz() { std::cout << "baz" << std::endl; }

}

int main(int argc, char **argv) {
  B::A a;
  bar(a);
  B::baz(); // simply calling baz() does not work

  return 0;
}

如果没有额外的资格,bar(a)如何被召唤?我原以为只有B::bar(a)会编译。

当函数在命名空间内没有参数时,不会发生这种情况。

1 个答案:

答案 0 :(得分:6)

根据ISO C ++ 14标准,§3.4.2:

  

当函数调用中的postfix-expression是非限定id时,可以搜索在通常的非限定查找期间未考虑的其他命名空间,并且在这些命名空间中,命名空间范围的朋友函数或函数模板声明不会可以找到可见。对搜索的这些修改取决于参数的类型(对于模板模板参数,模板参数的命名空间)。

以下:

  

对于函数调用中的每个参数类型T,都有一组零个或多个关联的命名空间以及一组零个或多个要考虑的关联类。命名空间和类的集合完全由函数参数的类型决定。

     

如果T是类类型(包括联合),则其关联的类是:类本身;它所属的成员,如果有的话;及其直接和间接基类。 其关联的命名空间是其关联类的最内层的命名空间

实际上,您甚至可以通过附上函数名称来阻止这种情况发生:

(bar)(a); // doens't compile

,而

(B::bar)(a); // does compile

请注意,这仅适用于最里面的命名空间,这意味着在以下情况下您需要限定命名空间:

namespace B {
   namespace C {
     struct A {};
   }

   void bar(const C::A& a) { ... }
}