c++ - 嵌套在函数中的函数声明的命名空间

标签 c++ namespaces language-lawyer forward-declaration

出于奇怪的原因,我想在函数范围内声明一个函数。 所以我得到以下代码:

namespace NS
{
    void foo()
    {
        void bar();
        bar();
    }
}

在另一个编译单元中,我想定义bar。 根据我使用的编译器,我需要将 bar 放在命名空间 NS 或全局命名空间中以便能够链接:

在 clang 中:

namespace NS
{
    void bar() {}
}

在 MSVC 上:

void bar() {}

什么是好的行为,如果有的话?

作为附带问题,为什么以下代码都没有编译(在我的 2 个编译器上):

namespace NS
{
    void foo()
    {
        void bar();
        ::bar(); // bar declared in global namespace
    }
}

namespace NS
{
    void foo()
    {
        void bar();
        ::NS::bar(); // bar declared in NS namespace
    }
}

感谢您的帮助。

吉西尔贝

最佳答案

Note: Long story, short; msvc is doing it wrong, and clang is correct. This post will explain why by showing relevant snippets, and having standard quotations to back up the claims.

关于第一个片段/问题


简介

block 作用域中的函数声明被称为引用最内层封闭命名空间中的实体,因此在下面的 bar 中引用 NS::bar

namespace NS {
  void foo () {
    void bar (); // (A), forward-declaration of `NS::bar`

    bar ();      // call (A)
  }
}

这意味着您在定义 bar 时,必须在命名空间 N 中执行此操作,或者使用 qualified-id 来引用给所述实体。

void f ():     // some other `void f()`;  _not_ (A)

void NS::f (); // same `f` as being declared at (A)

namespace NS {
  void f ();   // same `f` as being declared at (A)
}

标准是怎么说的? ( n3337 )

3.5p6 Program and linkage [basic.link]

The name of a function declared in block scope and the name of a variale declared by a block scope extern declaration have linkage. If there is a visible declaration of an enity with linkage having the same name and type, ignoring entities declared outside the innermost enclosing namespace scope, the block scope declaration declares the same entitiy and receives the linkage of the previous declaration. If there is more than one such matching entity, the program is ill-formed. Otherwise, if no matching entity is found, the block scope entity receives external linkage.


结论

msvc 做错了,clang 显示的行为是正确的。



关于第二个片段/问题


说明

当遇到 block 作用域声明时,它指的是最近的封闭命名空间中的实体,但它不会在该命名空间中引入这样的名称。

3.5p7 Program and linkage [basic.link]

When a block scope declaration of an entity with linkage is not found to refer to some other declaration, then that entity is a member of the innermost enclosing namespace. However such a declaration does not introduce the member name in its namespace scope.

看下面的例子:

namespace NS {
  void foo() {
    void bar();  // (A), forward-declaration of `NS::bar`
    ::NS::bar(); //      ill-formed, there is no `::NS::bar` yet
    bar ();      //           legal, call the `bar` being forward-declared by (A)
  }
}

在上面的 (A) 中指的是 ::NS::bar 的即将到来的声明,但是由于前向声明不会使 namespace NS 具有实体命名为 bar 我们只能通过 bar 引用将被称为 ::NS::bar 的实体。

void bar ();    // (A), `::bar`

namespace NS {
  void foo() {
    void bar();   // (B), forward-declaration of `NS::bar`

    ::bar();      // call (A)
    bar ();       // call (B), `NS::bar`

    ::NS::bar (); // ill-formed, `namespace NS` doesn't have an entity named bar (yet) 
  }

  void bar ();    // (C), make `NS` have an entity named bar, this is the one
                  //      being referred to by (B)

  void baz () {
    ::NS::bar (); // legal, `namespace NS` now have an entity named `bar`, as being
                  //        declared in (C)
  }
}

关于c++ - 嵌套在函数中的函数声明的命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24239846/

相关文章:

c++ - 为什么 "constructor-way"允许在 "for-loop"中声明变量,但不允许在 "if-statement"中声明变量?

c++ - 为什么我的程序在调用 main 之前就退出了?

c# - 什么是值继承和引用继承?

c++ - not "using namespace std; "给了我一个意外错误(C++)

javascript - 使用 Firefox Add-on Sdk 中的类和命名空间

c++ - 类成员转换函数-id

c - C99 中与调整参数相关的未定义行为

c++ - 如何在宿主程序调用 main() 函数之前构造 DLL 模块中的全局对象?

C++ pugiXML,在节点中的第一个子节点之前附加一个子节点

c++ - (C++) 无法引用命名空间内的枚举类