16.12. Пространства имен и шаблоны классов
16.12. Пространства имен и шаблоны классов
Как и любое определение в глобальной области видимости, определение шаблона класса можно поместить внутрь пространства имен. (Пространства имен рассматривались в разделах 8.5 и 8.6.) Наш шаблон будет скрыт в данном пространстве имен; лишь в этом отличие от ситуации, когда шаблон определен в глобальной области видимости. При употреблении вне пространства имя шаблона следует либо квалифицировать его именем, либо воспользоваться using-объявлением:
#include iostream
#include cstdlib
namespace cplusplus_primer {
template class Type
class Queue { // ...
};
template class Type
Type QueueType::remove()
{
// ...
}
}
Если имя Queue шаблона класса используется вне пространства имен cplusplus_primer, то оно должно быть квалифицировано этим именем или введено с помощью using-объявления. Во всех остальных отношениях шаблон Queue используется так, как описано выше: конкретизируется, может иметь функции-члены, статические члены, вложенные типы и т.д. Например:
int main() {
using cplusplus_primer Queue; // using-объявление
// ссылается на шаблон класса в пространстве имен cplusplus_primer
Queueint *p_qi = new Queue
int;
// ...
p_qi-remove();
}
Шаблон cplusplus_primer::Queue конкретизируется, так как использован в выражении new:
... = new Queueint;
p_qi - это указатель на тип класса cplusplus_primer::Queueint
Когда он применяется для адресации функции-члена remove(), то речь идет о члене именно этого конкретизированного экземпляра класса.
Объявление шаблона класса в пространстве имен влияет также на объявления специализаций и частичных специализаций шаблона класса и его членов (см. разделы 16.9 и 16.10). Такая специализация должна быть объявлена в том же пространстве имен, где и общий шаблон.
В следующем примере в пространстве имен cplusplus_primer объявляются специализации типа класса Queue и функции-члена remove() класса Queue:
#include iostream
#include cstdlib
namespace cplusplus_primer {
template class Type
class Queue { ... };
template class Type
Type QueueType::remove() { ... }
// объявление специализации
// для cplusplus_primer::Queuechar *
template class Queuechar* { ... };
// объявление специализации
// для функции-члена cplusplus_primer::Queuedouble::remove()
template double Queuedouble::remove() { ... }
}
Хотя специализации являются членами cplusplus_primer, их определения в этом пространстве отсутствуют. Определить специализацию шаблона можно и вне пространства имен при условии, что определение будет находиться в некотором пространстве, объемлющем cplusplus_primer, и имя специализации будет квалифицировано его именем :
namespace cplusplus_primer
{
// определение Queue и его функций-членов
}
// объявление специализации
// cplusplus_primer::Queuechar*
template class cplusplus_primer::Queueprimer::Queuechar* и функции-члена remove() для класса cplusplus_primer::Queue находятся в глобальной области видимости. Поскольку такая область содержит пространство имен cplusplus_primer, а имена специализаций квалифицированы его именем, то определения специализаций для шаблона Queue вполне законны.