Стандарт C++ следует читать очень внимательно, вникая в каждое слово написанного. Некоторые параграфы стандарта либо трудно понять, либо не сразу же обращаешь внимание на их смысл, пока не попробуешь с помощью компилятора или компиляторов осмыслить и проверить написанное.
Одно из таких "темных мест", которому при первом чтении можно не придать значение, касается расширения пространства имен. В самом начале раздела "
9.7.1 Namespace definition" стандарта C++ 20 имеется следующий параграф
цитата: |
2 In a named-namespace-definition, the identifier is the name of the namespace. If the identifier, when looked up (6.4.1), refers to a namespace-name (but not a namespace-alias) that was introduced in the namespace in which the named-namespace-definition appears or that was introduced in a member of the inline namespace set of that namespace, the namespace-definition extends the previously-declared namespace. Otherwise, the identifier is introduced as a namespace-name into the declarative region in which the named-namespace definition appears. |
|
Вы поняли, что написано? А из написанного вытекает следующее. Вы можете объявить пространство имен внутри множества он-лайновых пространств заданного пространства, а затем расширить его в заданном замыкающем пространстве вне множества от-лайновых пространств имен.
Чтобы было более понятно, приведу следующую демонстрационную программу.
#include <iostream>
inline namespace N1
{
inline namespace N2
{
namespace N3
{
void f( int ) { std::cout << "f( int )\n"; }
}
}
namespace N3
{
void f( char ) { std::cout << "f( char )\n"; }
}
}
int main()
{
N3::f( 10 );
N2::N3::f( 'A' );
}
Ее вывод на консоль:
f( int )
f( char )
Как видно из текста программы, пространство имен
N3 было объявлено в он-лайновом пространстве имен
N2 пространства имен
N1.
А затем пространство имен
N3 было расширено, но его расширение помещено не в пространство имен
N2, а непосредственно в пространство имен
N1.
Такое расширение допустимо.
Однако, если сначала поместить пространство имен
N3 внутрь пространства имен
N1, а затем расширение пространства имен
N3 вложить в он-лайновое пространство имен
N2, то соответствующая программа уже не будет компилироваться.
#include <iostream>
inline namespace N1
{
namespace N3
{
void f( char ) { std::cout << "f( char )\n"; }
}
inline namespace N2
{
namespace N3
{
void f( int ) { std::cout << "f( int )\n"; }
}
}
}
int main()
{
N3::f( 10 );
N2::N3::f( 'A' );
}
Компилятор сообщит о неоднозначности имени
N3.
Чтобы понять суть происходящего, то следует запомнить, что объявления в он-лайновых пространствах имен являются объявлениями и его замыкающего пространства. В то время как, объявления замыкающего пространства не являются объявлениями его он-лайновых вложенных пространств.