Обратные вызовы в C++ | страница 30
>template
>class StaticArray
>{
>public:
> type array[size];
>};
>template
>TYPE Sum(TYPE s2, TYPE s3)
>{
> return s2 + s3;
>}
>int main()
>{
> StaticArray
> int a = 0; double x = 8;
> Sum(a, a); // (4)
> Sum
>}
В строке 1 объявлен шаблон класса, в строке 2 объявлен шаблон функции. В строке 3 производится явное инстанциирование шаблона класса, типами параметров выступают int и числовое значение. В строке 4 производится неявное инстанциирование шаблона функции, тип параметра шаблона здесь будет int, который выводится из типа входного аргумента. В строке 5 производится явное инстанциирование; оно здесь необходимо, потому что из типов входных аргументов нельзя однозначно определить, какой тип параметра должен использоваться в шаблоне.
Вообще, шаблоны в C++ – это обширная тема, заслуживающая отдельной книги, поэтому изложить ее полностью не представляется возможным. Для лучшего понимания дальнейшего материала, кроме уже изложенных базовых понятий, рекомендуется ознакомиться со следующими темами: шаблоны с переменным числом параметров; частичная специализация шаблонов; автоматический вывод типов17.
Программирование с использованием шаблонов, или, как его еще называют, метапрограммирование, достаточно сложное, поскольку предполагает высокий уровень абстракции в сочетании с неявным генерированием кода на этапе компиляции. Здесь используется другая парадигма, которая очень отличается от привычного объектно-ориентированного подхода; по своей природе шаблоны ближе к функциональному программированию. Однако именно благодаря указанным особенностям они позволяют легко и естественно решать многие задачи, в которых использование классических средств C++ порождает немало проблем.
Применительно к нашей теме, т. е. проектированию обратных вызовов, с помощью шаблонов можно реализовать множество интересных вещей, как это будет показано в следующих главах. Начнем с синхронных вызовов, как наиболее простых.
4.2. Синхронные вызовы
4.2.1. Инициатор
Проанализируем различные реализации инициатора синхронных вызовов (Листинг 24):
>class Executor
>{
>public:
> void callbackHandler(int eventID);
> void operator() (int eventID);
>};
>using ptr_callback = void(*) (int, void*);
>using ptr_callback_static = void(*) (int, Executor*);