使用 using 指令进行限定名称查找的不同行为 使命名空间内联时

Different behavior for qualified name lookup with using-directive when making namespace inline

提问人:user10282772 提问时间:10/28/2020 最后编辑:user10282772 更新时间:10/31/2020 访问量:195

问:

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

问题如下所示:

prog1:命名空间在命名空间之外:CA

#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 Cnamespace A

prog2:命名空间在命名空间内:CA

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,两者的结果相同。

我的问题:

为什么结果不同,在此方案中限定名称查找的具体规则是什么?

C++ 命名空间 language-lawyer name-lookup using 指令

评论

0赞 Tiger Yu 10/28/2020
您使用哪种编译器?
0赞 cigien 10/28/2020
我编辑了标题和问题,使其更清晰一些。如果这以任何方式改变了您问题的含义,请告诉我。此外,由于您要求提供特定规则,因此可以考虑在问题中添加 language-lawyer 标记。如果这样做,则需要删除其他标签之一。您可以删除其中任何一个,它们都同样适用,当然:)除了 c++ 标签。

答:

0赞 Igor Tandetnik 10/31/2020 #1

[命名空间.udir]/2using 指令指定指定命名空间中的名称可以在 using 指令出现在 using 指令之后的作用域中使用。在非限定名称查找 (6.4.1) 期间,名称看起来就像是在最近包含 using 指令和指定命名空间的封闭命名空间中声明的一样。[注:在此上下文中,“包含”是指“直接或间接包含”。——尾注 ]

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

评论

0赞 user10282772 11/1/2020
此规则适用于非限定名称查找,但 A::D etail 是限定名称。
0赞 Igor Tandetnik 11/1/2020
A::Detail不会出现在显示的代码中,除非在字符串文本中显示。确实对DetailDetail::func()
0赞 user10282772 11/2/2020
对不起,我的意思是是一个限定名称,而不是.此规则仅适用于非限定名称。Detail::funcA::Detail
0赞 Igor Tandetnik 11/2/2020
就目前而言,这是真的。但是,在通过限定名称查找解析名称之前,必须通过非限定名称查找来解析名称。这就是产生歧义的地方。请仔细阅读错误消息:。引用 ,而不是Detail::funcDetailprog.cc:27:9: error: reference to 'Detail' is ambiguousDetailDetail::func