Введение

Узоры разработки программного обеспечения (Software design pattern) Узоры любопытно повторяющихся шаблонов (CRTP) - это идиом, изначально написанный на C++, в котором класс X получается из инстанцирования шаблона класса, используя сам X в качестве аргумента шаблона. Более широко это известно как F-связанный полиморфизм, и это форма F-связанного количественного определения.

История

Метод был официально утвержден в 1989 году как "F-ограниченное количественное определение". Название "CRTP" было независимо придумано Джимом Коплиеном в 1995 году, который наблюдал его в некоторых из самых ранних шаблонов C ++, а также в примерах кода, которые Тимоти Бадд создал в своем многопарадигматическом языке Leda. Иногда его называют "Верхняя Наследие" из-за того, что он позволяет расширять иерархию классов путем замены различных базовых классов. Microsoft Implementation of CRTP in Active Template Library (ATL) была независимо открыта, также в 1995 году, Яном Фалькиным, который случайно вывел базовый класс из выведенного класса. Кристиан Бомонт впервые увидел код Яна и сначала подумал, что он не может быть скомпилирован в компиляторе Microsoft, доступном в то время. После того, как стало известно, что это действительно работает, Кристиан основал весь дизайн ATL и Windows Template Library (WTL) на этой ошибке.

Недостатки

Одна проблема с статическим полиморфизмом заключается в том, что без использования общего базового класса, такого как AbstractShape из приведенного выше примера, производное класса не может храниться однородно, то есть помещать различные типы, полученные из одного базового класса, в один и тот же контейнер. Например, контейнер, определенный как std::vector<Shape*>, не работает, потому что Shape - это не класс, а шаблон, нуждающийся в специализации. Контейнер, определенный как std::vector<Shape<Circle>*>, может хранить только круги, а не квадраты. Это связано с тем, что каждый из классов, полученных из базового класса CRTP Shape, является уникальным типом. Общее решение этой проблемы - унаследовать от общего базового класса с виртуальным деструктором, как в примере AbstractShape выше, что позволяет создать std:: vector<AbstractShape*>.