Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Липпман.doc
Скачиваний:
8
Добавлен:
14.08.2019
Размер:
7.54 Mб
Скачать

16.12. Пространства имен и шаблоны классов

Как и любое определение в глобальной области видимости, определение шаблона класса можно поместить внутрь пространства имен. (Пространства имен рассматривались в разделах 8.5 и 8.6.) Наш шаблон будет скрыт в данном пространстве имен; лишь в этом отличие от ситуации, когда шаблон определен в глобальной области видимости. При употреблении вне пространства имя шаблона следует либо квалифицировать его именем, либо воспользоваться using-объявлением:

#include <iostream>

#include <cstdlib>

namespace cplusplus_primer {

template <class Type>

class Queue { // ...

};

template <class Type>

Type Queue<Type>::remove()

{

// ...

}


}

Если имя Queue шаблона класса используется вне пространства имен cplusplus_primer, то оно должно быть квалифицировано этим именем или введено с помощью using-объявления. Во всех остальных отношениях шаблон Queue используется так, как описано выше: конкретизируется, может иметь функции-члены, статические члены, вложенные типы и т.д. Например:

int main() {

using cplusplus_primer Queue; // using-объявление

// ссылается на шаблон класса в пространстве имен cplusplus_primer

Queue<int> *p_qi = new Queue<int>;

// ...

p_qi->remove();


}

Шаблон cplusplus_primer::Queue<int> конкретизируется, так как использован в выражении new:

... = new Queue<int>;

p_qi – это указатель на тип класса cplusplus_primer::Queue<int>. Когда он применяется для адресации функции-члена remove(), то речь идет о члене именно этого конкретизированного экземпляра класса.

Объявление шаблона класса в пространстве имен влияет также на объявления специализаций и частичных специализаций шаблона класса и его членов (см. разделы 16.9 и 16.10). Такая специализация должна быть объявлена в том же пространстве имен, где и общий шаблон.

В следующем примере в пространстве имен cplusplus_primer объявляются специализации типа класса Queue<char *> и функции-члена remove() класса Queue<double>:

#include <iostream>

#include <cstdlib>

namespace cplusplus_primer {

template <class Type>

class Queue { ... };

template <class Type>

Type Queue<Type>::remove() { ... }

// объявление специализации

// для cplusplus_primer::Queue<char *>

template<> class Queue<char*> { ... };

// объявление специализации

// для функции-члена cplusplus_primer::Queue<double>::remove()

template<> double Queue<double>::remove() { ... }


}

Хотя специализации являются членами cplusplus_primer, их определения в этом пространстве отсутствуют. Определить специализацию шаблона можно и вне пространства имен при условии, что определение будет находиться в некотором пространстве, объемлющем cplusplus_primer, и имя специализации будет квалифицировано его именем :

namespace cplusplus_primer

{

// определение Queue и его функций-членов

}

// объявление специализации

// cplusplus_primer::Queue<char*>

template<> class cplusplus_primer::Queue<char*> { ... };

// объявление специализации функции-члена

// cplusplus_primer::Queue<double>::remove()

template<> double cplusplus_primer::Queue<double>::remove()


{ ... }

Объявления специализаций класса cplusplus_primer::Queue<char*> и функции-члена remove() для класса cplusplus_primer::Queue<double> находятся в глобальной области видимости. Поскольку такая область содержит пространство имен cplusplus_primer, а имена специализаций квалифицированы его именем, то определения специализаций для шаблона Queue вполне законны.