Место в программе, где происходит конкретизация шаблона, называется точкой конкретизации. Она определяет, какие объявления принимаются компилятором во внимание для имен, зависящих от параметров шаблона.

Точка конкретизации шаблона всегда находится в области видимости пространства имен и непосредственно предшествует объявлению или определению, которое ссылается на конкретизированный экземпляр. Точка конкретизации функции-члена или статического члена шаблона класса всегда следует непосредственно за объявлением или определением, которое ссылается на конкретизированный член.

В предыдущем примере точка конкретизации Queue находится перед main(), и при разрешении зависящих от параметров имен, которые используются в определении шаблона Queue, компилятор просматривает все объявления до этой точки. Аналогично при таком разрешении в определении remove() компилятор просматривает все объявления до точки конкретизации, расположенной после main().

Как отмечалось в разделе 16.2, шаблон конкретизируется, если он используется в контексте, требующем полного определения класса. Члены шаблона не конкретизируются автоматически вместе с ним, а лишь тогда, когда сами используются в программе. Поэтому точка конкретизации шаблона класса может не совпадать с точками конкретизации его членов, да и сами члены могут конкретизироваться в разных точках. Чтобы избежать ошибок, объявления имен, упоминаемых в определениях шаблона и его членов, рекомендуется помещать в заголовочные файлы, включая их перед первой конкретизацией шаблона класса или любого из его членов.

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

Как и любое определение в глобальной области видимости, определение шаблона класса можно поместить внутрь пространства имен. (Пространства имен рассматривались в разделах 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

{

Перейти на страницу:

Похожие книги