Неоднозначная ссылка на пространство имен внутри встроенного пространства имен
Предположим, что следующий код:
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 { }
{
^
Какой компилятор делает правильную вещь здесь?
Ответы
Ответ 1
GCC верен:
Члены встроенного пространства имен могут использоваться в большинстве случаев, как если бы они были членами охватывающего пространства имен. В частности, встроенное пространство имен и его охватывающее пространство имен одновременно добавляются к набору связанных пространств имен, используемых в зависимом от аргументов поиске (3.4.2), когда каждый из них, и директива using, которая называет пространство имен, неявно вставлена в охватываемое пространство имен, как для неназванного пространства имен (7.3.1.1). Кроме того, каждый член встроенного пространства имен впоследствии может быть явно инстанцирован (14.7.2) или явно специализирован (14.7.3), как если бы он был членом охватывающего пространства имен. Наконец, поиск имени в охватывающем пространстве имен с помощью явной квалификации (3.4.3.2) будет включать в себя членов встроенного пространства имен, внесенного с помощью директивы using, даже если есть объявления этого имени в охватывающем пространстве имен.
(Это в 7.3.1/8 в старой нумерации n3337)
Я считаю, что вы видите Ошибка Clang # 10361.
Ответ 2
GCC верен.
N3797 утверждает, что
и директиву по использованию ( 7.3.4), который называет встроенное пространство имен, неявно вставляется в охватываемое пространство имен как для неназванного пространства имен ( 7.3.1.1).
Таким образом, test::detail
не является тем же самым пространством имен, что и test::v1::detail
, поэтому поиск test::detail
неоднозначен. Стандарт исключительно ясен, что поиск test::detail
должен включать test::v1::detail
, в этом разделе есть много кавычек, но нечего утверждать, что их следует считать одним и тем же пространством имен.
Возможно, я бы сказал, что поведение Клана превосходит, но GCC верен.