内联命名空间中对命名空间的模糊引用

Gri*_*wes 16 c++ g++ clang++ inline-namespaces c++14

假设以下代码:

namespace test 
{ 
    namespace detail 
    { 
    }

    inline namespace v1 
    { 
        namespace detail 
        { 
            void foo() 
            { 
            }
        }
    }
}

int main()
{ 
    test::detail::foo(); 
}
Run Code Online (Sandbox Code Playgroud)

我们可以看到,这段代码与Clang编译; 然而,与海湾合作委员会没有关系 - 海湾合作委员会抱怨说这namespace detail是不明确的:

main.cpp:20:11: error: reference to 'detail' is ambiguous
     test::detail::foo(); 
           ^
main.cpp:4:5: note: candidates are: namespace test::detail { }
     { 
     ^
main.cpp:10:9: note:                 namespace test::v1::detail { }
         { 
         ^
Run Code Online (Sandbox Code Playgroud)

哪个编译器在这里做正确的事情?

Lig*_*ica 13

GCC是正确的:

内联命名空间的成员可以在大多数方面使用,就像它们是封闭命名空间的成员一样.具体而言,内联命名空间及其封闭命名空间都被添加到参数依赖查找(3.4.2)中使用的关联命名空间集合中,只要其中一个是,并且命名空间using-directive被隐式插入到封闭中命名空间和未命名的命名空间(7.3.1.1).此外,内联命名空间的每个成员随后可以显式实例化(14.7.2)或显式专用(14.7.3),就像它是封闭命名空间的成员一样.最后,通过显式限定(3.4.3.2)查找封闭命名空间中的名称将包括using-directive引入的内联命名空间的成员,即使在封闭命名空间中存在该名称的声明也是如此.

(旧版n3337编号为7.3.1/8)

我相信你看到了Clang bug#10361.


Pup*_*ppy 5

GCC是正确的.

N3797说,

和命名内联命名空间的using-指令(7.3.4)隐式插入到封闭的命名空间中,与未命名的命名空间一样(7.3.1.1).

因此,test::detail与名称空间不同test::v1::detail,因此查找test::detail是不明确的.标准非常清楚,test::detail应该包括查找,test::v1::detail本节中有许多引号来支持这一点,但没有说明它们应该被认为是相同的命名空间.

可以说,我会说Clang的行为是优越的,但GCC是正确的.