【问题标题】:Different behavior for qualified name lookup with using-directive when making namespace inline使命名空间内联时,使用 using 指令进行限定名称查找的不同行为
【发布时间】:2021-02-10 11:34:53
【问题描述】:

我正在学习 using-directives,并试图了解 using-directive 的名称查找规则,但我遇到了这个问题,我找不到任何解释。

问题如下:

prog1:命名空间C在命名空间A之外:

#include <iostream>
namespace C
{
    namespace Detail
    {
        void func()
        {
            std::cout << "C::Detail::func " << "\n";
        }
    }
}

namespace A
{
    namespace Detail
    {
        void func()
        {
            std::cout << "A::Detail::func " << "\n";
        }
    }

    using namespace C;

    void func2()
    {
        Detail::func();  // no conflict, select A::Detail::func
    }
}

int main()
{
    A::func2();
    return 0;
}

程序成功,执行,输出A::Detail::func

当我将namespace C 移动到namespace A 内部时,出现编译器错误:

prog2:命名空间C在命名空间A内:

namespace A
{
    namespace C
    {
        namespace Detail
        {
            void func()
            {
                std::cout << "C::Detail::func " << "\n";
            }
        }
    }

    namespace Detail
    {
        void func()
        {
            std::cout << "A::Detail::func " << "\n";
        }
    }

    using namespace C;

    void func2()
    {
        Detail::func();    // conflict for A::Detail::func and A::C::Detail::func
    }
}

int main()
{
    A::func2();
    return 0;
}

程序有这个编译器错误:

prog.cc:27:9: error: reference to 'Detail' is ambiguous
        Detail::func();
        ^
prog.cc:15:15: note: candidate found by name lookup is 'A::Detail'
    namespace Detail
              ^
prog.cc:6:19: note: candidate found by name lookup is 'A::C::Detail'
        namespace Detail
                  ^
1 error generated.

编译器:GCC 9.3.0 和 CLANG 9.0.0,结果相同。

我的问题:

为什么结果不一样,这个场景下限定名查找的具体规则是什么?

【问题讨论】:

  • 你使用哪个编译器?
  • 我编辑了标题和问题,使其更加清晰。请让我知道这是否会以任何方式改变您问题的含义。此外,由于您要求特定规则,您可能会考虑将language-lawyer 标签添加到问题中。如果这样做,则需要删除其他标签之一。你可以删除它们中的任何一个,它们都同样适用,当然除了 c++ 标签:)。

标签: c++ namespaces language-lawyer name-lookup using-directives


【解决方案1】:

[namespace.udir]/2 using-directive 指定指定命名空间中的名称可以在 using-指令 出现在 using-directive 之后。在非限定名称查找 (6.4.1) 期间,名称出现好像它们是在最近的封闭命名空间中声明的,其中包含 using-directive 和指定的命名空间。 [ 注意: 在此上下文中,“包含”是指“直接或间接包含”。 ——尾注 ]

强调我的。在 prog1 中,最近的封闭命名空间是全局命名空间,A::Detail 位于 ::Detail 之前。在 prog2 中,最近的封闭命名空间是 A,因此名称查找会找到两个不同的命名空间,均名为 A::Detail

【讨论】:

  • 这条规则适用于非限定名查找,但A::Detail是限定名。
  • A::Detail 没有出现在显示的代码中,除了在字符串文字中。确实对出现在Detail::func() 中的名称Detail 执行了非限定名称查找
  • 抱歉,我的意思是 Detail::func 是限定名称,而不是 A::Detail。此规则仅适用于非限定名称。
  • 这是真的,就目前而言。但在名称Detail::func 可以通过限定名称查找解析之前,名称Detail 必须通过非限定名称查找解析。这就是产生歧义的地方。仔细阅读错误信息:prog.cc:27:9: error: reference to 'Detail' is ambiguous。参考Detail,而不是Detail::func
猜你喜欢
  • 2014-08-05
  • 1970-01-01
  • 2015-04-11
  • 2015-10-06
  • 2011-02-26
  • 2011-02-20
  • 2020-05-20
  • 2017-02-14
  • 2022-10-14
相关资源
最近更新 更多