Я разрабатываю дизайн приложения, и я подумал, что мог бы применить какой-то шаблон Visitor design , но оказалось, что это не совсем то, что я ищу.Может быть, кто-то может указать мне вариант, который мне нужен в этом случае?
Большая часть моего кода имеет аргумент шаблона "ContainerType", например
template <class ContainerType>
class MyClass
{
public:
void doSomething(ContainerType& container) { ... }
};
В настоящее время существует небольшое, но растущее число«Контейнеры», которые обычно совместно используют много полей данных.
template<class ContainedType>
struct ContainerBase
{
ContainedType data;
};
struct Container1: ContainerBase<A>, ContainerBase<B>
{};
struct Container2: ContainerBase<A>, ContainerBase<C>
{};
Container1 и Container2 теперь используются в качестве аргументов шаблона для MyClass (и других), где A, B, C - некоторые определенные классы.(У меня есть какой-то метод, чтобы сделать что-то вроде get<A>(container)
для доступа к содержащимся данным. Этот дизайн обеспечивает безопасность во время компиляции, что MyClass может использоваться со всеми типами контейнеров, которые содержат требуемые типы.)
Теперь я хотел быхотелось бы добавить функцию, которая «если Контейнер содержит определенный тип (например, A), то делает что-то, иначе ничего не делает».
Это может быть сделано с чем-то, что выглядит как посетитель (но обратите внимание, что нетиспользуются виртуальные методы).Он даже позволяет «если Контейнер содержит A, делать это, если он содержит D, делать что-то еще, иначе ничего не делать».Это может быть сделано с помощью
template <class ContainerType>
class MyClass
{
public:
void doSomething(ContainerType& container)
{
container.accept(*this);
}
void visit(B& b){...}
void visit(D& d){...}
template<typename T>
void visit(T& t){}
};
struct Container1: ContainerBase<A>, ContainerBase<B>
{
template<class T>
void accept(T& t)
{
t.visit(ContainerBase<A>::data);
t.visit(ContainerBase<B>::data);
}
};
Это то, что я хотел, но я ищу лучший способ сделать это, потому что реализация, показанная здесь, требует реализации accept для каждого ContainerType.Если кто-то происходит от Container1
и ContainerBase<D>
, но забывает расширять методы приема, все станет плохо.Хуже того, мне потребуется константная и неконстантная версия accept, а некоторые контейнеры содержат> 5 типов, поэтому это тоже не будет выглядеть красиво.
Все классы контейнеров создаются путем наследования от ContainerBase<T>
Несколько раз, поэтому я задавался вопросом, могу ли я использовать эту структуру для реализации accept (и accept (..) const) в классе ContainerBase?Я уже посмотрел на списки типов Lokis, но я не знаю, как их использовать здесь.У вас есть какие-либо идеи?
Или это возможно сделать без структуры, похожей на посетителя?
Большое спасибо!
РЕДАКТИРОВАТЬ: Я знаю, что я мог бы пойтис RTTI, но я бы хотел по возможности избегать проверок во время выполнения и виртуальных методов.