C++ Программирование в среде С++ Builder 5

Специализация шаблона функции


Несколько напоминает перегрузку шаблонов ситуация, когда определяется обычная функция, имя которой совпадает с именем шаблона и список параметров которой соответствует шаблону с некоторым специфическим набором фактических типов. Такую функцию называют специализированной функцией шаблона. Этот прием применяют, когда для некоторого типа или набора типов общий шаблон работать не будет.

Допустим, мы хотим, чтобы шаблон Мах()из последнего примера порождал функцию для двух аргументов-строк, которая возвращала бы большую из них (в смысле алфавитного порядка). Функция Мах (char*, char*), порожденная из первого шаблона, сравнивала бы адреса строк вместо их содержимого. Поэтому нужно определить отдельную функцию Мах (char*, char*):

char *Max(char *a, char *b) {

return strcmp(a, b) > 0? а : b;

}

Когда компилятор встречает вызов какой-то функции, для его разрешения он следует такому алгоритму:

  • Сначала ищется обычная функция с соответствующими параметрами.
  • Если таковой не найдено, компилятор ищет шаблон, из которого можно было бы генерировать функцию с точным соответствием параметров.
  • Если этого сделать невозможно, компилятор вновь рассматривает обычные функции на предмет возможных преобразований типа параметров.
  • Ниже приводится полный пример, иллюстрирующий различные аспекты перегрузки и специализации шаблонов.

    Листинг 10.1. Перегрузка и специализация шаблона



    ////////////////////////////////////////////////////////

    // Functemp.cpp: Шаблоны функций.

    //

    #include <string.h>

    #include <iostream.h>

    #pragma hdrstop

    #include <condefs.h>

    // Возвращает больший из двух аргументов.

    template <class Т> Т Мах(Т а, Т b) {

    return a > b? a : b;

    }

    // Возвращает наибольший элемент массива.

    template <class Т> Т Мах(Т аrr[], size_t size) {

    Т maxVal = arr[0] ;

    for(unsigned i=l; i<size; i++)

    if (arr[i] > maxVal)

    maxVal = arr[i] ;

    return maxVal;

    }

    // Возвращает большую из двух строк.

    char *Max(char *a, char *b)

    {

    return strcmp(a, b) > 0? а : b;


    }

    // Вызывается для целочисленных аргументов // различающихся типов. long Max(long a, long b)

    {

    return Max<long>(a, b);

    }

    #pragma argsused int main(int argc, char* argv[])

    {

    int il = 11, i2 = 22;

    float fl = 1.11, f2 = 22.2;

    char str1[] = "First string.";

    char str2[] = "Second string.";

    char с = 33;

    cout << "Max int: " << Max(il, i2) << endl;

    cout<< "Max float: " “ Max(fl, f2) << endl;

    cout << "Max element: "<< Max(strl, strlen(strl)) << endl;

    cout << "Max string: " << Max(strl, str2) << endl;

    cout << "Max(int,char): " << Max(i1, c) << endl;

    return 0;

    }

    Последнее определение—Max (long, long) — требует некоторых пояснений. Эта специализированная функция вызывает явным образом функцию шаблона для сравнения двух аргументов фактического типа long. Но какой в этом смысл?

    Если не определить такую функцию, компилятор вообще не сможет вызвать, например, Мах (int, char), как в последнем операторе вывода. (Подобные сравнения являются на самом деле “признаком дурного тона”.) Имеется только шаблон, два параметра которого имеют один и тот же тип, а как говорилось выше, компилятор использует шаблон только в том случае, если можно получить точное соответствие параметров типам аргументов в вызове. Однако благодаря определению специализированной функции компилятор может разрешить вызов, преобразовав char в long.

    На рисунке показан результат работы программы.



    Рис. 10.1 Программа Functemp


    Содержание раздела