假设以下代码:
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 { }
{
^
哪个编译器在这里做正确的事情?
答案 0 :(得分:13)
GCC是正确的:
内联命名空间的成员可以在大多数方面使用,就像它们是封闭命名空间的成员一样。具体而言,内联命名空间及其封闭命名空间都被添加到依赖于参数的查找(3.4.2)中使用的关联命名空间集合中,只要其中一个是,并且 a 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。
答案 1 :(得分:5)
GCC是正确的。
N3797表示,
和使用指令( 7.3.4)对于未命名的命名空间,内联命名空间的名称隐式插入到封闭的命名空间中( 7.3.1.1)。
因此,test::detail
与test::v1::detail
的名称空间不同,因此test::detail
的查找不明确。标准非常明确,test::detail
的查找应该包含test::v1::detail
,本节中有很多引号可以支持这一点,但没有说明它们应该被视为相同的命名空间。
可以说,我会说Clang的行为更优越,但GCC是正确的。