Каковы некоторые практические применения для Любопытно повторяющийся шаблонный шаблон "?" подсчитанный класс "пример, который обычно показан, не является для меня убедительным примером.
Практическое использование для "любопытно повторяющегося шаблона шаблона"
Ответ 1
Имитированное динамическое связывание. Избежание стоимости вызовов виртуальных функций при сохранении некоторых из иерархических преимуществ - огромная победа для подсистем, где это можно сделать в проекте, над которым я сейчас работаю.
Ответ 2
Это также особенно полезно для mixins (под которым я подразумеваю классы, которые вы наследуете для обеспечения функциональности), которые сами должны знать, на каком типе они работают (и, следовательно, должны быть шаблонами).
В Effective С++ Скотт Мейерс представляет собой пример шаблона класса NewHandlerSupport <T> . Он содержит статический метод переопределения нового обработчика для определенного класса (так же, как std:: set_new_handler делает для нового оператора по умолчанию) и оператора new, который использует обработчик. Чтобы обеспечить обработчик per-type, родительский класс должен знать, на каком типе он действует, поэтому он должен быть шаблоном класса. Параметр шаблона - это дочерний класс.
Вы не могли бы сделать это без CRTP, так как вам нужно создать экземпляр NewHandlerSupport отдельно, с отдельным статическим членом данных для хранения текущего new_handler для каждого класса, который его использует.
Очевидно, что весь пример чрезвычайно безопасен для потоков, но он иллюстрирует точку.
Майерс предполагает, что CRTP можно рассматривать как "Сделай это для меня". Я бы сказал, что это обычно относится к любому mixin, и CRTP применяется в случае, когда вам нужен шаблон mixin, а не только класс mixin.
Ответ 3
CRTP становится намного менее любопытным, если вы считаете, что тип подкласса, который передается суперклассу, необходим только во время расширения метода. Итак, все типы определены. Вам просто нужен шаблон для импорта символьного типа подкласса в суперкласс, но это просто объявление вперед - поскольку все формальные типы шаблонов шаблона по определению - в отношении суперкласса.
Мы используем несколько модифицированную форму, передавая подкласс в структуре типа признаков суперклассу, чтобы позволить суперклассу возвращать объекты производного типа. Приложение представляет собой библиотеку для геометрического исчисления (точки, векторы, линии, прямоугольники), где все универсальные функциональные возможности реализованы в суперклассе, а подкласс определяет конкретный тип: CFltPoint наследует от TGenPoint. Также CFltPoint существовал до TGenPoint, поэтому подкласс был естественным способом рефакторинга этого.
Ответ 4
Обычно он используется для полиморфных шаблонов, где вам не нужно выбирать производный класс во время выполнения, только во время компиляции. Это может сэкономить накладные расходы на вызов виртуальной функции во время выполнения.
Ответ 5
Для использования библиотеки CRTP в реальном мире посмотрите на ATL и WTL (wtl.sf.net). Он широко используется для полиморфизма времени компиляции.
Ответ 6
Он похож на макрос C: воспользуйтесь тем, что макрос компилируется не во время определения, а во время использования.
#define CALL_THE_RIGHT_FOO foo()
файл A:
static void foo() {
// do file A thing
}
...
CALL_THE_RIGHT_FOO
...
файл A:
static void foo() {
// do file B thing
}
...
CALL_THE_RIGHT_FOO
...
Шаблон использования шаблона, который вы описываете, позволяет нам "вызывать правильное foo" в родительском шаблоне, откладывая определение того, что именно является правильным foo до момента создания шаблона. За исключением этого случая, это различие между ClassA:: foo и ClassB:: foo на основе значения T в Parent.