Параметр шаблона класса может и не быть типом. На аргументы, подставляемые вместо таких параметров, накладываются некоторые ограничения. В следующем примере мы изменяем определение класса Screen (см. главу 13) на шаблон, параметризованный высотой и шириной:
template <int hi, int wid>
class Screen {
public:
Screen() : _height( hi ), _width( wid ), _cursor ( 0 ),
_screen( hi * wid, '#' )
{ }
// ...
private:
string _screen;
string::size_type _cursor;
short _height;
short _width;
};
typedef Screen<24,80> termScreen;
termScreen hp2621;
Screen<8,24> ancientScreen;
Выражение, с которым связан параметр, не являющийся типом, должно быть константным, т.е. вычисляемым во время компиляции. В примере выше 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_val = 1024;
const int c_size_val = 1024;
Buf< 1024 > buf0; // правильно