内联命名空间中对命名空间的不明确引用

Posted

技术标签:

【中文标题】内联命名空间中对命名空间的不明确引用【英文标题】:Ambiguous reference to namespace within an inline namespace 【发布时间】:2014-10-15 15:38:03 【问题描述】:

假设以下代码:

namespace test 
 
    namespace detail 
     
    

    inline namespace v1 
     
        namespace detail 
         
            void foo() 
             
            
        
    


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

As we can see,这段代码用Clang编译;不是 with 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  
          
         ^

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

【问题讨论】:

Clang apparently gets others things about inline namespaces wrong,设计或遗漏。 【参考方案1】:

GCC 是正确的。

N3797 指出,

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

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

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

【讨论】:

【参考方案2】:

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。

【讨论】:

以上是关于内联命名空间中对命名空间的不明确引用的主要内容,如果未能解决你的问题,请参考以下文章

当存在内联命名空间时,如何显式引用封闭的命名空间?

[C/C++]C++的命名空间,缺省参数,引用,auto关键字,内联函数等

C++入门(命名空间缺省参数函数重载引用内联函数)

C++入门语法第一篇:(命名空间缺省参数函数重载引用内联函数)

C++初阶:入门总结命名空间 | 缺省参数 | 函数重载 | 引用 | 内联函数

C++入门(命名空间,缺省参数,函数重载,引用,内联函数,auto,范围for)