Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Аргументы шаблона для параметров-констант
Параметр шаблона класса может и не быть типом. На аргументы, подставляемые вместо таких параметров, накладываются некоторые ограничения. В следующем примере мы изменяем определение класса Screen (см. главу 13) на шаблон, параметризованный высотой и шириной:
Screen< 8, 24> ancientScreen; Выражение, с которым связан параметр, не являющийся типом, должно быть константным, т.е. вычисляемым во время компиляции. В примере выше typedef termScreen ссылается на экземпляр шаблона Screen< 24, 80>, где аргумент шаблона для hi равен 24, а для wid – 80. В обоих случаях аргумент – это константное выражение. Однако для шаблона BufPtr конкретизация приводит к ошибке, так как значение указателя, получающееся при вызове оператора new(), становится известно только во время выполнения:
BufPtr< new int[24] > bp; Не является константным выражением и значение неконстантного объекта. Его нельзя использовать в качестве аргумента для параметра-константы шаблона. Однако адрес любого объекта в области видимости пространства имен, в отличие от адреса локального объекта, является константным выражением (даже если спецификатор const отсутствует), поэтому его можно применять в качестве аргумента для параметра-константы. Константным выражением будет и значение оператора sizeof:
Buf< size_val > buf3; Вот еще один пример, иллюстрирующий использование параметра-константы для представления константного значения в определении шаблона, а также применение его аргумента для задания значения этого параметра:
FixedArray< int, sizeof( is ) / sizeof( int ) > iA{ ia ); Выражения с одинаковыми значениями считаются эквивалентными аргументами для параметров-констант шаблона. Так, все три экземпляра Screen ссылаются на один и тот же конкретизированный из шаблона класс Screen< 24, 80>:
Screen< width, height > scr2; Между типом аргумента шаблона и типом параметра-константы допустимы некоторые преобразования. Их множество является подмножеством преобразований, допустимых для аргументов функции: · трансформации l-значений, включающие преобразование l-значения в r-значение, массива в указатель и функции в указатель:
BufPtr< array > bpObj; // преобразование массива в указатель · преобразования квалификаторов:
Ptr< & iObj > pObj; // преобразование из int* в const int* · расширения типов:
Screen< shi, swi > bpObj2; // расширения типа short до int · преобразования целых типов:
Buf< 1024 > bpObj; // преобразование из int в unsigned int (Более подробно они описаны в разделе 9.3.) Рассмотрим следующие объявления:
Array< int, x, foo> a5; // ошибка: foo! = PFV Объекты a0 и a4 класса Array определены правильно, так как аргументы шаблона точно соответствуют типам параметров. Объект a2 также определен правильно, потому что аргумент 1024 типа int приводится к типу unsigned int параметра-константы size с помощью преобразования целых типов. Объявления a1, a3 и a5 ошибочны, так как не существует преобразования между любыми двумя типами функций. Приведение значения 0 целого типа к типу указателя недопустимо:
BufPtr< 0 > nil; Упражнение 16.3 Укажите, какие из данных конкретизированных шаблонов действительно приводят к конкретизации:
} Упражнение 16.4 Какие из следующих конкретизаций шаблонов корректны? Почему?
template < int hi, int wid > class Screen {... };
Ptr< & size > bp1;
(c) Ptr < 0 > bp3;
Screen< hi, wi+32 > sObj;
Fixed_Array< string, size_val > fa1;
Fixed_Array< int, fasize > fa2;
Fixed_Array< double, db > fa3; |
Последнее изменение этой страницы: 2019-04-09; Просмотров: 307; Нарушение авторского права страницы