Допустимо ли в C++ выполнять шаблонную специализацию функции внутри встроенного пространства имен в пространстве за пределами встроенного пространства имен?
Например, будет ли это скомпилироваться?
namespace A
{
inline namespace A0
{
namespace B
{
template<typename T>
T sum(T v1, T v2)
{
return v1 + v2;
}
}
}
}
namespace A
{
namespace B
{
template<>
float sum<float>(float v1, float v2)
{
return v1 - v2; // Do something different
}
}
}
В настоящее время этот код компилируется с g++ 13.02, но не с MSVC 19.40 для c++17.
https://eel.is/c++draft/namespace.def.general#2:
В определении именованного пространства имен D идентификатором является имя пространства имен. Идентификатор ищется путем его поиска в областях пространства имен A, в котором появляется D, и каждого элемента встроенного набора пространств имен A. Если поиск находит определение пространства имен для пространства имен N, D расширяет N, и целевая область D — это область, к которой принадлежит N.
Итак, во второй раз в вашем примере появляется пространство имен с именем B
:
namespace A
{
namespace B
{
// ...
}
}
Поиск находит пространство имен A::A0::B
, так что новое пространство имен расширяет первое пространство имен с именем B
точно так же, как если бы вы написали:
namespace A::inline A0::B {
// ...
}
Таким образом, когда sum
ищется по имени в явной специализации, он находит шаблон A::A0::B::sum
, на котором он может хорошо специализироваться.
Итак, я думаю, это ошибка в компиляторе msvc.
@TedLyngmo Я имел в виду явную специализацию. Поиск происходит потому, что eel.is/c++draft/temp.expl.spec#3 eel.is/c++draft/dcl.meaning.general#3.3
@EdwinLesterSolisFuentes Да, GCC здесь прав. Clang также, кажется, справляется с этим правильно.
Встроенные пространства имен на самом деле были разработаны для обеспечения такого рода вещей: идея состоит в том, что автор пространства имен A может переключать подпространство имен, которое является встроенным, в то время как клиенты могут продолжать специализировать шаблоны, которые объявлены в одном из подподпространств имен, не подвергаясь воздействию этого выбора. .