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