«Будьте внимательны с терминологией. Шаблон функции не является функцией. Прототип шаблона функции — maximum< T >( Т , Т ), а функция, которую создаёт данный шаблон при замене Т на int, — maximum ( int , int ) ( это уже функция, а не шаблон ).»
[Атас!]
Заметим, что следующий код всё равно оказывается неработоспособным:
double d = maximum( 1 , 2.0 ) ;
_________________
310 стр. Часть 5. Полезные особенности
Проблема в том, что типы первого и второго аргументов различны, а при инстанцировании типы аргументов должны точно соответствовать объявлению функции. Приведённое же выражение может соответствовать шаблону maximum< T1 , Т2 > ( Т1 , Т2 ) ( тогда С++ заменит Т1 на int , а Т2 на double ), но не использовавшемуся ранее шаблону с одним аргументом типа.
Вы можете заставить С++ инстанцировать шаблон, использовав в программе объявление требуемой функции:
float maximum( float , float ) ; /* Заставляет С++ */
/* инстанцировать шаблон функции */
/* maximum< T >( Т , Т ) для Т = float */
«С++ даже не пытается компилировать шаблон функции до тех пор, пока шаблон не будет преобразован в реальную функцию. Если ваш шаблон содержит ошибки, вероятно, вы не узнаете о них до тех пор, пока не инстанцируете его.»
[Атас!]
►Шаблоны классов...311
С++ позволяет программисту определять шаблоны классов. Шаблон класса следует тем же принципам, что и использование обычного класса, с заменой фиктивного неизвестного типа известным на этапе компиляции. Например, в приведённой далее программе создаётся вектор некоторого пользовательского класса ( вектор — это контейнер, в котором объекты хранятся в линейном порядке, так что массив является классическим примером вектора ).
/* TemplateVector — реализация шаблона вектора */
#include
#include
#include
#include
#include
using namespace std ;
/* TemplateVector — простой шаблон массива */
template < class T >
class TemplateVector
{
public :
TemplateVector( int nArraySize )
{
/* Количество элементов массива */
nSize = nArraySize ;
array = new T[ nArraySize ] ;
reset( ) ;
}
int size( ) { return nWriteIndex ; }
void reset( ) { nWriteIndex = 0 ; nReadIndex = 0 ; }
void add( T object )
{
if ( nWriteIndex < nSize )
{
array[ nWriteIndex++ ] = object ;
}
}
T get( )
{
_________________
311 стр. Глава 27. Шаблоны С++
return array[ nReadIndex++ ] ;
}
protected :
int nSize ;
int nWriteIndex ;
int nReadIndex ;
T* array ;
} ;
/* Работа с двумя векторами — целых чисел и имён */
void intFn( ) ;
void nameFn( ) ;
int main( int argc , char* pArgs[ ] )
{
setlocale ( LC_ALL , ".1251" ) ; /* печать русских текстов */
intFn( ) ;
nameFn( ) ;
/* Пауза для того, чтобы посмотреть на результат работы программы */
system( "PAUSE" ) ; return 0 ;
}
/* Работа с целыми числами */
void intFn( )
{
/* Создание вектора */
TemplateVector< int > integers( 10 ) ;
/* Добавляем значения в вектор */
cout << "Введите последовательность целых чисел\n"
"для внесения в вектор ( отрицательное\n"
"число завершает ввод последовательности )"
<< endl ;
for ( ; ; )
{
int n ;
cin >> n ;
if ( n < 0 ) { break ; }
integers.add( n ) ;
}