17

假设以下代码:

namespace test 
{ 
    namespace detail 
    { 
    }

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

int main()
{ 
    test::detail::foo(); 
}

正如我们所见,这段代码是用 Clang 编译的;不是GCC,但是 - GCC 抱怨引用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 { }
         { 
         ^

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

4

2 回答 2

13

海湾合作委员会是正确的:

内联命名空间的成员在大多数情况下都可以使用,就好像它们是封闭命名空间的成员一样。具体来说,内联命名空间及其封闭命名空间都被添加到参数相关查找(3.4.2)中使用的关联命名空间集合中,只要其中一个存在,并且命名命名空间using 指令隐式插入到封闭命名空间中命名空间与未命名的命名空间 (7.3.1.1) 相同。此外,内联命名空间的每个成员随后都可以显式实例化(14.7.2)或显式特化(14.7.3),就好像它是封闭命名空间的成员一样。最后,通过显式限定在封闭的命名空间中查找名称(3.4.3.2)将包括由using 指令引入的内联命名空间的成员,即使在封闭的命名空间中有该名称的声明

(这是旧 n3337 编号中的 7.3.1/8)

我相信您会看到Clang 错误 #10361

于 2014-08-21T21:16:03.293 回答
5

海湾合作委员会是正确的。

N3797 指出,

和一个命名内联命名空间的 using 指令 ​​( 7.3.4 ) 被隐式插入到封闭的命名空间中,就像未命名的命名空间 ( 7.3.1.1 ) 一样。

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

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

于 2014-08-21T21:23:18.800 回答