Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OOAP.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
494.59 Кб
Скачать

4.3. Аргументы шаблона для параметров-констант

Параметр шаблона класса может и не быть типом. На аргументы, подставляемые вместо таких параметров, накладываются некоторые ограничения.

template <int hi, int wid>

class Screen {

public:

Screen(): height(hi), width(wid), cursor(0)

{ }

// ...

private:

int cursor;

short height;

short width;

};

typedef Screen<24,80> termScreen;

termScreen scr;

Screen<8,24> scr2;

Выражение, с которым связан параметр, не являющийся типом, должно быть константным, т.е. вычисляемым во время компиляции. В примере выше typedef termScreen ссылается на экземпляр шаблона Screen<24,80>, где аргумент шаблона для hi равен 24, а для wid - 80. В обоих случаях аргумент - это константное выражение.

Однако для шаблона BufPtr конкретизация приводит к ошибке, так как значение указателя, получающееся при вызове оператора new(), становится известно только во время выполнения:

template <int *ptr> class BufPtr {...};

// ошибка: аргумент шаблона нельзя вычислить во время компиляции

BufPtr<new int[24]> bp;

Не является константным выражением и значение неконстантного объекта. Его нельзя использовать в качестве аргумента для параметра-константы шаблона. Однако адрес любого объекта в области видимости пространства имен, в отличие от адреса локального объекта, является константным выражением (даже если спецификатор const отсутствует), поэтому его можно применять в качестве аргумента для параметра-константы. Константным выражением будет и значение оператора sizeof:

template <int size> Buf {...};

template <int *ptr> class BufPtr {...};

int size_v = 512;

const int c_size_v = 1024;

Buf<1024> buf0; // правильно

Buf<c_size_v> buf1; // правильно

Buf<sizeof(size_v) > buf2; // правильно: sizeof(int)

BufPtr<&size_v> bp0; // правильно

// ошибка: нельзя вычислить во время компиляции

Buf<size_v> buf3;

Вот еще один пример, иллюстрирующий использование параметра-константы для представления константного значения в определении шаблона, а также применение его аргумента для задания значения этого параметра:

template <class Type, int size>

class FixArray {

public:

FixArray(Type *ar): count(size)

{

for(int ix = 0; ix < size; ++ix)

array[ix] = ar[ix];

}

private:

Type array[size];

int count;

};

int ia[4] = {0, 1, 2, 3};

FixedArray<int, sizeof(ia)/sizeof(int)> iA(ia);

Выражения с одинаковыми значениями считаются эквивалентными аргументами для параметров-констант шаблона. Так, все три экземпляра Screen ссылаются на один и тот же конкретизированный из шаблона класс Screen<24,80>:

const int width = 24;

const int height = 80;

// все далее Screen< 24, 80 >

Screen<2*12, 40*2> scr0;

Screen<6+6+6+6, 20*2 + 40> scr1;

Screen<width, height> scr2;

Между типом аргумента шаблона и типом параметра-константы допустимы некоторые преобразования. Их множество является подмножеством преобразований, допустимых для аргументов функции. Рассмотрим следующие объявления:

extern void foo( char * );

extern void bar( void * );

typedef void (*PFV)( void * );

const unsigned int x = 1024;

template <class Type,

unsigned int size,

PFV handler> class Array { ... };

Array<int, 1024U, bar> a0; // правильно: преобразование не нужно

Array<int, 1024U, foo> a1; // ошибка: foo != PFV

Array<int, 1024, bar> a2; // правильно: 1024 преобразуется в unsigned int

Array<int, x, bar> a3; // правильно: преобразование не нужно

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

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

template <int *ptr>

class BufPtr { ... };

BufPtr<0> nil; // ошибка: 0 имеет тип int

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]