Специализация шаблонов, которой нет
В некоторых случаях бывает необходимо предоставить реализацию шаблона для конкретного типа (или набора типов), так чтобы она отличалась от общего варианта. Например, обычно имеет смысл подготовить особую версию функции swap (обмена значениями) для указателей или массивов. В подобных случаях С++ позволяет сделать специализацию шаблона, то есть определить его версию, в которой обобщенный параметр типа T заменен на требуемый конкретный тип.
При специализации шаблонов функций и методов должны быть заданы конкретные типы для всех параметров. Это называется полной специализацией.
В случае шаблонов объектных типов C++ специализация может быть не только полной, но и частичной: при ней уточняется тип лишь некоторых из параметров (а остальные будут выводиться или указываться при создании экземпляра шаблона). Частичных специализаций может быть несколько: единственное условие для этого — каждая специализация должна описывать уникальное сочетание типов.
К сожалению, в MQL5 нет специализации в полном смысле этого слова.
Специализация шаблонной функции ничем не отличается от перегрузки. Например, при наличии следующего шаблона func:
template<typename T>
|
допускается предоставить его особую реализацию для заданного типа (такого как string) в одной из форм:
// явная специализация
|
или:
// обычная перегрузка
|
Должна быть выбрана только одна из форм. Иначе получим ошибку компиляции "'func' - функция уже определена и имеет тело" ("'func' - function already defined and has body").
Что касается специализации классов, то неким эквивалентом их частичной специализации можно считать наследование от шаблонов с указанием конкретных типов для части шаблонных параметров. В производном классе методы шаблона можно переопределить.
В следующем примере (TemplatesExtended.mq5) показано несколько вариантов использования параметров шаблонов в качестве родительских типов, в том числе и случаи, когда один из них прописан конкретным.
#define RTTI Print(typename(this))
|
Инстанцирование объекта по шаблону обеспечим с помощью переменной:
Derived2<Derived1<Base>> derived2; |
Отладочный вывод типов в журнал с помощью макроса RTTI дает следующий результат:
Base
|
При разработке библиотек, которые поставляются в виде закрытого двоичного кода, необходимо обеспечить явное создание экземпляров шаблонов для всех типов, с которыми предполагается работа будущими пользователями библиотеки. Сделать это можно, вызвав явным образом шаблоны функций и создав объекты с указанием параметров-типов в какой-либо вспомогательной функции, например, привязанной к инициализации глобальной переменной.