Использование CRTP в цепочке вызовов

В моей библиотеке виджетов я хотел бы реализовать какую-то цепочку вызовов для инициализации
предоставленный пользователем класс VIEW, который может (!) быть производным от другого класса, который добавляет
некоторые дополнительные функции, такие как это:

#include <iostream>

template<typename VIEW>
struct App
{
VIEW view;
void init() {view.initialize(); }
};

template<typename DERIVED>
struct SpecializedView
{
void initialize()
{
std::cout << "SpecializedView" << std::endl;
static_cast<DERIVED*>(this)->initialize();
}
};

struct UserView : SpecializedView<UserView>
{
void initialize() {std::cout << "UserView" << std::endl; }
};

int _tmain(int argc, _TCHAR* argv[])
{
// Cannot be altered to: App<SpecializedView<UserView> > app;
App<UserView> app;
app.init();
return 0;
}

Можно ли достичь какой-то цепочки вызовов (если пользовательский класс VIEW является производным от «SpecializedView»), так что результат будет:

console output:

SpecializedView
UserView

Конечно, было бы легко создать экземпляр приложения с типом, полученным из
но этот код скрыт в библиотеке и не должен изменяться.
Другими словами: код библиотеки должен получать только пользовательский тип в качестве параметра.

2

Решение

Вы могли бы написать другую функцию, которая вызывает initialize() на классе и на базовом классе, если он существует и определяет initialize() метод тоже:

template <class T>
void callInitialize(T* t) {
t->initialize();
IF_EXISTS(base_class<T>::bc::initialize)
callInitialize<base_class<T>::bc>(t);
}

Конечно, порядок звонков можно поменять местами.

Увидеть Можно ли написать шаблон для проверки существования функции? на реализацию IF_EXISTS, Также, base_class<T> не является стандартной конструкцией, и этот ответ предполагает, что это не может быть сделано автоматически. Семантика будет выглядеть так:

template<T>
struct base_class<T> {
typedef void bc;
};

template<>
struct base_class<UserView> {
typedef SpecializedView<UserView> bc;
};

Возможно, ваша структура позволяет полуавтоматический способ сделать это.

1

Другие решения

Других решений пока нет …