Выбрать главу

Arrayint, x, foo a5; // ошибка: foo != PFV

Объекты a0 и a4 класса Array определены правильно, так как аргументы шаблона точно соответствуют типам параметров. Объект a2 также определен правильно, потому что аргумент 1024 типа int приводится к типу unsigned int параметра-константы size с помощью преобразования целых типов. Объявления a1, a3 и a5 ошибочны, так как не существует преобразования между любыми двумя типами функций.

Приведение значения 0 целого типа к типу указателя недопустимо:

template int *ptr

class BufPtr { ... };

// ошибка: 0 имеет тип int

// неявное преобразование в нулевой указатель не применяется

BufPtr 0 nil;

Упражнение 16.3

Укажите, какие из данных конкретизированных шаблонов действительно приводят к конкретизации:

template class Type

class Stack { };

void f1( Stack char ); // (a)

class Exercise {

// ...

Stack double // (b)

Stack int si; // (c)

};

int main() {

Stack char *sc; // (d)

f1( *sc ); // (e)

int iObj = sizeof( Stack string ); // (f)

}

Упражнение 16.4

Какие из следующих конкретизаций шаблонов корректны? Почему?

template int *ptr class Ptr ( ... };

template class Type, int size class Fixed_Array { ... };

template int hi, int wid class Screen { ... };

(a) const int size = 1024;

Ptr &size&bp1;

(b) int arr[10];

Ptr arr bp2;

(c) Ptr 0 bp3;

(d) const int hi = 40;

const int wi = 80;

Screen hi, wi+32 sObj;

(e) const int size_val = 1024;

Fixed_Array string, size_val fa1;

(f) unsigned int fasize = 255;

Fixed_Array int, fasize fa2;

(g) const double db = 3.1415;

Fixed_Array double, db fa3;

16.3. Функции-члены шаблонов классов

Как и для обычных классов, функция-член шаблона класса может быть определена либо внутри определения шаблона (и тогда называется встроенной), либо вне его. Мы уже встречались со встроенными функциями-членами при рассмотрении шаблона Queue. Например, конструктор Queue является встроенным, так как определен внутри определения шаблона класса:

template class Type

class Queue {

// ...

public:

// встроенный конструктор

Queue() : front( 0 ), back( 0 ) { }

// ...

};

При определении функции-члена шаблона вне определения самого шаблона следует применять специальный синтаксис для обозначения того, членом какого именно шаблона является функция. Определению функции-члена должно предшествовать ключевое слово template, за которым следуют параметры шаблона. Так, конструктор Queue можно определить следующим образом:

template class Type

class Queue {

public:

Queue();

private:

// ...

};

template class Type

inline Queue Type ::

Queue( ) { front = back = 0; }

За первым вхождением Queue (перед оператором ::) следует список параметров, показывающий, какому шаблону принадлежит данная функция-член. Второе вхождение Queue в определение конструктора (после оператора ::) содержит имя функции-члена, за которым может следовать список параметров шаблона, хотя это и необязательно. После имени функции идет ее определение;. в нем могут быть ссылки на параметр шаблона Type всюду, где в определении обычной функции использовалось бы имя типа.

Функция-член шаблона класса сама является шаблоном. Стандарт C++ требует, чтобы она конкретизировалась только при вызове либо при взятии ее адреса. (Некоторые более старые компиляторы конкретизируют такие функции одновременно с конкретизацией самого шаблона класса.) При конкретизации функции-члена используется тип того объекта, для которого функция вызвана:

Queue string qs;

Объект qs имеет тип Queue string . При инициализации объекта этого класса вызывается конструктор Queuestring. В данном случае аргументом, которым конкретизируется функция-член (конструктор), будет string.

Функция-член шаблона конкретизируется только при реальном использовании в программе (т.е. при вызове или взятии ее адреса). От того, в какой именно момент конкретизируется функция-член, зависит разрешение имен в ее определении (см. раздел 16.11) и объявление ее специализации (см. раздел 16.9).

16.3.1. Функции-члены шаблонов Queue и QueueItem

Чтобы понять, как определяются и используются функции-члены шаблонов классов, продолжим изучение шаблонов Queue и QueueItem:

template class Type

class Queue {

public:

Queue() : front( 0 ), back ( 0 ) { }