Выбор базового класса CRTP для наследования

Допустим, у меня есть следующий очень простой базовый класс CRTP:

template< class D, class T >
struct Base
{

T foo()
{
return static_cast< D* >(this)->foo_i();
}

};

А также, несколько производных классов. Все работает хорошо, но есть проблема: есть один конкретная ситуация (или, возможно, пара), где я бы действительно очень как два класса, чтобы иметь полиморфное поведение во время выполнения (нужно поместить их в контейнеры). Другими словами, я хотел бы, чтобы некоторые из производных классов CRTP также имели виртуальные версии. Итак, я придумал следующий класс:

template< class T >
struct VirtualBase : public Base< VirtualBase< T >, T >
{

virtual T foo_i() = 0;

};

Теперь, когда мне нужен полиморфизм времени исполнения, я просто наследую этот класс. Допустим, я хочу свой производный класс DerivedB иметь виртуальную версию. Ванильный DerivedB выглядит так:

template< class T >
struct DerivedB : public Base< DerivedB< T >, T >
{

T foo_i()
{
std::cout << "I'm special!\n";
return T();
}

};

По сути, я хотел бы добавить дополнительный параметр шаблона к этому классу, чтобы я мог во время компиляции выбрать, наследовать ли я от Base (если я хочу смоделированное «динамическое» связывание) или VirtualBase (если я хочу реальное динамическое связывание) ). Что-то вроде следующего псевдо-C ++:

template< class B, class T >
struct DerivedB : public B< DerivedB< T >, T >
{

T foo_i()
{
std::cout << "I'm special!\n";
return T();
}

};

Так что для простого CRTP, пройти Base как B и для виртуального класса, пройти VirtualBase как B, Проблема, конечно, в том, что они принимают разное количество аргументов (Base нужен тип производного класса), и я не могу найти рабочее решение.

Итак, как бы я выбрал базовый класс во время компиляции? Или, если это слишком сложно / невозможно, каков будет самый простой способ иметь статические (CRTP) и динамические (виртуальные) версии класса, где в противном случае реализация идентична?

1

Решение

Возможно, самый простой способ — просто добавить «класс D» в качестве неиспользуемого параметра шаблона VirtualBase, чтобы он соответствовал тому же интерфейсу.

Если вы не можете изменить VirtualBase, вы можете использовать промежуточный шаблон:

template <class D, class T> class VirtualBaseWrapper : public VirtualBase<T>{}
2

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

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

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector