【问题标题】:Nesting unnamed namespaces嵌套未命名的命名空间
【发布时间】:2011-06-15 13:31:59
【问题描述】:

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

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

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

据我所见,foos 都将获得每个编译单元的内部唯一标识符,并且可以使用 A::foo 访问 - 但是否存在我不知道的细微或不那么细微的区别看到了吗?

【问题讨论】:

  • (已编辑)您可以通过在文件级别声明另一个 A::foo 来有效地隐藏第二个 foo。第一个foo 将始终可以作为::A::foo 访问。除非您重新打开 A 并在那里声明另一个 foo。也就是说,是的,几乎相同。

标签: c++ namespaces


【解决方案1】:

和你输入的完全一样,没有区别。

当然,你可以在展位示例的第一级命名空间中添加声明,然后会有所不同。

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(依赖于参数的名称查找),我理解对于其他 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 构造函数调用B::foo( ),即使上面有using namespace A。 要在 BClass 析构函数上调用 A::foo( ),调用必须明确限定。

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

如果我们考虑嵌套的 named 命名空间以及如何解决与参数相关的问题,也许会更清楚。 olny 的区别将是隐含的 using 对未命名的,但它不会改变编译器首选项。

【讨论】:

  • 我认为您的访问示例是倒退的。第一个是A::i,第二个是i
  • 虽然到目前为止这是一个极好的答案,但我想知道命名空间会对 ADL 产生什么样的影响 - namespace A {void bar();} 能够在任何示例中找到 foo () 吗?
猜你喜欢
  • 2011-01-06
  • 2018-02-03
  • 1970-01-01
  • 2015-01-08
  • 2015-07-13
  • 1970-01-01
  • 1970-01-01
  • 2021-10-26
  • 2011-03-13
相关资源
最近更新 更多