假设以下代码:
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 { }
{
^哪个编译器在这里做正确的事情?
发布于 2014-08-21 21:16:03
GCC说得对:
内联命名空间的成员可以在大多数方面被使用,就好像他们是封闭名称空间的成员一样。随参数相关的查找(3.4.2)中使用的关联命名空间集合(3.4.2)中,内联命名空间及其包围名称空间都会添加到其中一个名称空间中;命名名称空间的名称空间的名称空间( using-directive )与未命名的名称空间(7.3.1.1)一样,被隐式地插入到封闭名称空间中。此外,内联命名空间的每个成员随后都可以显式实例化(14.7.2)或显式专门化(14.7.3),就好像它是封闭命名空间的成员一样。最后,通过显式qualifi阳离子 (3.4.3.2)在封闭名称空间中查找名称,它将包含由引入的内联名称空间的成员,即使在封闭名称空间中有该名称的声明。
(旧n3337编号为7.3.1/8 )
我相信你看到Clang bug #10361了。
发布于 2014-08-21 21:23:18
GCC是对的。
N3797说,
命名内联名称空间的使用指令( 7.3.4 )与未命名的命名空间( 7.3.1.1 )一样,被隐式插入到封闭命名空间中。
因此,test::detail与test::v1::detail不是同一个名称空间,因此test::detail的查找是不明确的。标准非常清楚,test::detail的查找应该包括test::v1::detail,在本节中有许多引号来支持这一点,但没有说明它们应该被视为相同的名称空间。
可以说,我认为Clang的行为是优越的,但GCC的行为是正确的。
https://stackoverflow.com/questions/25435897
复制相似问题