嵌套未命名命名空间

16

这两种未命名命名空间的嵌套用法之间是否存在功能上的差别:

namespace A { namespace {
  void foo() {/*...*/}
}}

namespace { namespace A {
  void foo() {/*...*/}
}}

就我所看到的,每个编译单元都会为两个foo分配一个内部唯一标识符,并且可以使用A::foo访问它们-但是我是否有任何细微或不太明显的差异没有看到?


1
你可以通过在文件级别声明另一个A::foo来有效地隐藏第二个foo。第一个foo将始终可访问为::A::foo。除非你重新打开A并在那里声明另一个foo。也就是说,这几乎是相同的。 - n. m.
1个回答

8

与您输入的完全一样,没有区别。

当然,您可以在第一级命名空间中添加声明以展示不同之处,这样就会有所不同。

namespace A {
  int i;         // Accessed globally in this file as "A::i".
  namespace {
    void foo() {/*...*/}
}}


namespace {
  int i;         // Accessed globally in this file simply as "i".
  namespace A {
    void foo() {/*...*/}
}}}

请注意,尽管您作为程序员无法区分,但对于编译器来说,命名空间是不同的。
unnamed_namespaces.cpp:42:5: error: reference to ‘A’ is ambiguous
unnamed_namespaces.cpp:19:17: error: candidates are: namespace A { }
unnamed_namespaces.cpp:28:19: error:                 namespace <unnamed>::A { }

有用:


编辑:

关于ADL(Argument-dependent name lookup),我理解对于其他foo()的重载决议不会有优先级差异,如下所示:

#include    <iostream>

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

namespace A {
    namespace {
        void foo() { std::cout << "A::<unnamed>::foo()" << std::endl; }

        class   AClass
        {
        public:
            AClass( )
            {   foo( ); }
        };
    }
}


namespace {
    namespace B {
        void foo() { std::cout << "B::<unnamed>::foo()" << std::endl; }

        using namespace A;

        class   BClass
        {
        public:
            BClass( )
            {   foo( ); }

            ~BClass( )
            {   A::foo( );  }
        };
    }
}

int main( )
{
    A::foo( );
    B::foo( );
    foo( );

    A::AClass   a;
    B::BClass   b;

    return  0;
}

编译器会优先选择最近的foo( ),除非显式指定。 因此,即使在BClass构造函数中有using namespace A语句,BClass构造函数还是调用了B::foo( )。 要在BClass析构函数中调用A::foo( ),必须显式限定调用。

A::<unnamed>::foo()
B::<unnamed>::foo()
::foo()
A::<unnamed>::foo()
B::<unnamed>::foo()
A::<unnamed>::foo()

也许如果我们考虑嵌套的“命名空间”以及如何解决参数相关性,这个问题就会变得更加清晰。唯一的区别是未命名空间上会有一个隐式的“using”,但这不会改变编译器的偏好。

2
我认为你的访问示例是反过来的。第一个是 A::i,第二个只是 i - Dennis Zickefoose
虽然这是一个非常出色的答案,但我想知道命名空间对 ADL 有什么影响 - namespace A {void bar();} 是否能够在任何示例中找到 foo() - ltjax

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接