ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.12.2020
Просмотров: 4317
Скачиваний: 28
Часть II. Язык программирования С++
266
шаблона
должен содержать аргументы частичной специализации
шаблона класса.
Например, если объявление первичного шаблона класса имеет
вид:
template <class S, class T> class Demo;
то объявления частичных специализаций этого шаблона могут
иметь следующий вид:
template <class S, class T> class Demo<*S, T>;
template<class S> class Demo<S, *S>;
template<class S> class Demo<S, int>;
Определение частичной специализации никак не связано с опре-
делением первичного шаблона класса, для которого может быть
совершенно другой набор членов, а также собственные определе-
ния функций-членов. Содержащиеся в первичном шаблоне класса
определения никогда не употребляются для конкретизации чле-
нов его частичной специализации.
Отметим, что компилятор может и не конкретизировать шаблон
класса по причине неоднозначности его специализаций, которые
получены из определения первичного шаблона класса и его час-
тичных специализаций. Для решения этой задачи специализации
шаблона класса частично упорядочивают. Частичный порядок на
специализациях шаблона класса строится по аналогии с частич-
ным порядком специализаций перегруженных шаблонных функ-
ций. То есть параметры шаблона класса рассматриваются как па-
раметры шаблонной функции и дальше применяются правила
упорядочивания специализаций шаблонных функций.
При конкретизации шаблона класса компилятор
частично упоря-
дочивает
специализации шаблона класса, полученные из первич-
ного шаблона и частичных специализаций этого шаблона класса.
После чего выбирается наилучшая специализация. Если такая
отсутствует, то компилятор выдает ошибку.
В заключение этого раздела заметим, что частичную специализа-
цию шаблонов классов поддерживают не все компиляторы.
Глава 19. Шаблоны классов
267
19.6. Статические члены
шаблона класса
В шаблоне класса могут быть объявлены статические данные-
члены класса. Каждый конкретизированный экземпляр шаблона
класса имеет собственный набор таких членов.
Если тип статического атрибута класса является параметром
шаблона класса, то и сам такой атрибут является шаблоном. Так
как статические атрибуты класса только объявляются внутри
класса, то шаблон статического атрибута класса должен быть оп-
ределен вне шаблона класса. Любой статический член шаблона
класса конкретизируется только в том случае, если он реально
используется в программе.
В листинге 19.8 приведен пример работы со статическими члена-
ми шаблона класса.
Листинг 19.8. Статические члены шаблона класса
#include <iostream>
using namespace std;
template <class T> struct Demo
{
static T d;
static void set(T _d) { d = _d; }
};
template<class T> T Demo<T>::d = 10;
int main()
{
Demo<int>::d += 10;
cout << Demo<int>::d << endl; // печатает 20
Demo<int>::set(5);
cout << Demo<int>::d << endl; // печатает 5
return 0;
}
Часть II. Язык программирования С++
268
19.7. Шаблоны как члены
шаблона класса
Шаблоны функции или класса могут быть членами шаблона
класса. Объявление шаблона-члена в шаблоне класса имеет соб-
ственные параметры. Для шаблона-члена шаблона класса дейст-
вуют те же правила доступа
public
,
protected
и
private
, что и для
других членов класса.
Например, в листинге 19.9 определен шаблон класса, членами
которого являются шаблон класса и шаблон функции.
Листинг 19.9. Шаблон класса с шаблонами-членами
#include <iostream>
using namespace std;
template <class T1> class Demo
{
T1 d;
public:
Demo(const T1& _d): d(_d) {}
template <class T2> struct Inner
{
T1 n;
T2 m;
};
template<class T3> T3 add(T3 const &p1, T3 const &p2)
{
T3 t;
t = p1 + p2;
return t;
};
};
int main()
{
Demo<double> d(10.5);
Глава 19. Шаблоны классов
269
Demo<int>::Inner<int> in;
in.n = 10;
in.m = 20;
int a = d.add(10,20);
cout << a << endl; // 30
return 0;
}
19.8. Объявление друзей
в шаблоне класса
В шаблоне класса можно объявить друзей шаблона класса. После
конкретизации шаблона класса эти друзья станут друзьями полу-
ченной специализации шаблона класса. Друзей шаблона класса
можно разбить на три группы:
друзья шаблона класса, которые не являются шаблонами;
друзья шаблона класса, которые сами являются шаблонами, и
их параметры связаны с параметрами шаблона класса;
друзья шаблона класса, которые сами являются шаблонами, и
их параметры не связаны с параметрами шаблона класса.
К первой группе друзей шаблона класса принадлежат обычные
функции и классы, которые объявлены в шаблоне класса с клю-
чевым словом
friend
.
В листинге 19.10 приведен пример функции
what
, объявленной
другом шаблона класса
Demo
.
Листинг 19.10. Функция-друг шаблона класса
#include <iostream>
using namespace std;
template <class T> class Demo
{
static int n;
Часть II. Язык программирования С++
270
public:
const T& foo(const T& t) { return t; }
friend int what() { return 10; }
};
template<class T> int Demo<T>::n = 10;
int main()
{
Demo<int> d;
cout << what() << endl; // печатает 10
cout << d.foo(20) << endl; // печатает 20
return 0;
}
Ко второй группе друзей шаблона класса принадлежат шаблоны
функций и классов, которые объявлены в шаблоне класса с клю-
чевым словом
friend
, и параметры этих шаблонов являются так-
же параметрами шаблона рассматриваемого класса. В этом слу-
чае говорят, что параметры друзей шаблона класса связаны с па-
раметрами шаблона класса.
Например, в листинге 19.11 приведен пример шаблона функции,
параметром которой является параметр-тип шаблона класса.
Листинг 19.11. Шаблон функции-друга шаблона класса
#include <iostream>
using namespace std;
template <class T> class Demo
{
T t;
public:
Demo(T _t): t(_t) {};
T get() { return t; }
template <class T> friend T add(Demo<T> &d, T t);
};
template <class T> T add(Demo<T> &d, T t) { return d.t + t; }