Namespace of a function declaration nested in function

ぃ、小莉子 提交于 2021-01-02 18:47:05

问题


For odd reasons, I want to declare a function inside a function scope. So I get the following code :

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

In another compilation unit, I want to define bar. Depending on the compiler I'm using, I need to put bar in namespace NS or in the global namespace to be able to link:

On clang:

namespace NS
{
    void bar() {}
}

On MSVC:

void bar() {}

What's the good behavior, if any ?

As a side question, why is none of the following code compiling (on my 2 compilers):

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

or

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

Thank you for your help.

GiSylbe


回答1:


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.

About the first snippet/question


Introduction

A function-declaration in block scope is said to refer to an entity in the innermost enclosing namespace, so in the below bar is referring to NS::bar.

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

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

This means that you, upon defining bar, must do so in either namespace N, or by using a qualified-id to refer to said entity.

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)
}

What does the standard say? (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.


Conclusion

msvc is doing it wrong, the behavior shown by clang is the correct one.



About the second snippet/question


Explanation

When a block-scope declaration is encountered it is referring to an entity in the closest enclosing namespace, but it does not introduce such name in that namespace.

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.

See the below example:

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)
  }
}

In the above (A) refers to an upcoming declaration of ::NS::bar, but since a forward-declaration does not make namespace NS have an entity named bar we can only refer to the entity that will be known as ::NS::bar through 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)
  }
}


来源:https://stackoverflow.com/questions/24239846/namespace-of-a-function-declaration-nested-in-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!