C++中嵌套函数声明的范围

0x5*_*9df 14 c++ scope namespaces language-lawyer c++11

namespace X {
    void f();
}

void X::f() {
    void g();
    g();
}
Run Code Online (Sandbox Code Playgroud)

我宣布了::g,还是X::g

如果我添加一个定义X::g:clang 3.5将编译并链接这个:

namespace X {
    void f();
}

void X::f() {
    void g();
    g();
}

void X::g() { }
Run Code Online (Sandbox Code Playgroud)

gcc 4.9.1用消息拒绝定义:

错误:'void X :: g()'应该在'X'内声明

但是,如果我g在全局命名空间中定义,gcc似乎改变了它的想法并且抱怨相反:

Undefined symbols for architecture x86_64:
  "X::g()", referenced from:
      X::f()     in ccABCDEF.o
Run Code Online (Sandbox Code Playgroud)

因为void ::g()在内部声明也是非法的f,似乎不可能在命名空间函数中具有全局函数的函数范围前向声明.我错过了什么吗?这里的范围规则究竟是什么?

g ++(GCC)4.9.1; Apple LLVM 6.0版(clang-600.0.54)(基于LLVM 3.5svn)

Col*_*mbo 6

块范围内的函数声明具有链接.[basic.link]/6:

在块作用域中声明的函数的名称和[..]具有链接.

但是这种带有链接的块作用域声明不会将任何名称引入封闭的名称空间.[basic.link]/7:

当找不到具有链接的实体的块范围声明来引用其他声明时,该实体是最内层封闭命名空间的成员.但是,此类声明不会在其命名空间范围中引入成员名称.

因此你既没有声明::g也没有X::g.通过定义它

void X::g() {}
Run Code Online (Sandbox Code Playgroud)

是不正确的.