Вбудовані простори імен - це функція версії бібліотеки, схожа на версію символів , але реалізована суто на рівні C ++ 11 (тобто крос-платформа) замість того, щоб бути особливістю певного бінарного виконуваного формату (тобто для платформи).
Це механізм, за допомогою якого автор бібліотеки може зробити вкладений простір імен і виглядати так, ніби всі його декларації знаходились у навколишньому просторі імен (вбудовані простори імен можуть бути вкладені, тому "більш вкладені" імена переповнюються аж до першого -введіть простір імен і подивіться та дійте так, ніби їхні декларації були і в одному з просторів імен між ними).
Як приклад, розглянемо реалізацію STL для vector
. Якби у нас були вбудовані простори імен з початку C ++, то в C ++ 98 заголовок, <vector>
можливо, виглядав би так:
namespace std {
#if __cplusplus < 1997L // pre-standard C++
inline
#endif
namespace pre_cxx_1997 {
template <class T> __vector_impl; // implementation class
template <class T> // e.g. w/o allocator argument
class vector : __vector_impl<T> { // private inheritance
// ...
};
}
#if __cplusplus >= 1997L // C++98/03 or later
// (ifdef'ed out b/c it probably uses new language
// features that a pre-C++98 compiler would choke on)
# if __cplusplus == 1997L // C++98/03
inline
# endif
namespace cxx_1997 {
// std::vector now has an allocator argument
template <class T, class Alloc=std::allocator<T> >
class vector : pre_cxx_1997::__vector_impl<T> { // the old impl is still good
// ...
};
// and vector<bool> is special:
template <class Alloc=std::allocator<bool> >
class vector<bool> {
// ...
};
};
#endif // C++98/03 or later
} // namespace std
Залежно від значення вибирається __cplusplus
або одна, або інша vector
реалізація. Якщо кодовий була написано в попередньо C ++ 98 разів, і ви виявите , що C ++ 98 версії vector
викликають проблеми для вас , коли ви оновити ваш компілятор, «все» ви повинні зробити , це знайти посилання на std::vector
в вашу кодову базу та замініть їх на std::pre_cxx_1997::vector
.
Приходьте на наступний стандарт, а STL продавець просто повторює процедуру знову, вводячи новий простір імен для std::vector
з emplace_back
підтримкою (що вимагає C ++ 11) і вбудовування , що один IFF __cplusplus == 201103L
.
Гаразд, чому для цього мені потрібна нова мовна функція? Я вже можу зробити наступне, щоб мати такий же ефект, ні?
namespace std {
namespace pre_cxx_1997 {
// ...
}
#if __cplusplus < 1997L // pre-standard C++
using namespace pre_cxx_1997;
#endif
#if __cplusplus >= 1997L // C++98/03 or later
// (ifdef'ed out b/c it probably uses new language
// features that a pre-C++98 compiler would choke on)
namespace cxx_1997 {
// ...
};
# if __cplusplus == 1997L // C++98/03
using namespace cxx_1997;
# endif
#endif // C++98/03 or later
} // namespace std
Залежно від значення __cplusplus
, я отримую або одну, або іншу реалізації.
І ти був би майже прав.
Розглянемо наступний дійсний код користувача C ++ 98 (було дозволено повністю спеціалізувати шаблони, які вже існують у просторі імен std
на C ++ 98):
// I don't trust my STL vendor to do this optimisation, so force these
// specializations myself:
namespace std {
template <>
class vector<MyType> : my_special_vector<MyType> {
// ...
};
template <>
class vector<MyOtherType> : my_special_vector<MyOtherType> {
// ...
};
// ...etc...
} // namespace std
Це абсолютно дійсний код, коли користувач надає власну реалізацію вектора для набору типів, де вона, мабуть, знає більш ефективну реалізацію, ніж та, яка знайдена в (її копії) STL.
Але : спеціалізуючись на шаблоні, вам потрібно зробити це в просторі імен, про яке було оголошено. Стандарт говорить, що vector
оголошено в просторі імен std
, тому користувач справедливо розраховує спеціалізувати тип.
Цей код працює з неперевершеним простором імен std
або з функцією просторового простору імен C ++ 11, але не з використовуваним трюком версії using namespace <nested>
, оскільки це розкриває деталі реалізації, що справжній простір імен, в якому vector
було визначено, не був std
безпосередньо.
Є й інші дірки, за допомогою яких можна було виявити вкладений простір імен (див. Коментарі нижче), але вбудовані простори імен підключають їх усі. І це все є. Неймовірно корисно для майбутнього, але Стандарт AFAIK не призначає вбудовані імена простору імен для власної стандартної бібліотеки (хоча б хотілося, щоб у цьому помилялися), тому його можна використовувати лише для сторонніх бібліотек, не сам стандарт (якщо виробники компілятора не погоджуються щодо схеми імен).
using namespace V99;
не працює на прикладі Stroustrup.