Ниже я вынул функцию accept (const ChooseVisitor&);
из Object
и разместил ее в Menu<T>::Option
вместо этого, так что ее нужно было бы назвать там вместо многих классов, которые будут иметь функцию accept
. Единственная проблема заключается в том, что T
может быть указателем или ссылкой или что-то еще, и мне нужно превратиться в обычный тип без указателя или ссылки или const и т. Д., Чтобы получить T::Visitor*
для компиляции.Ациклический шаблон посетителя. Перемещение функции accept только на одно место
#include <iostream>
#include <type_traits>
struct ChooseVisitor {
virtual ~ChooseVisitor() = default;
};
struct Object {
struct Visitor {
virtual void visit (Object*) const = 0;
};
// void accept (const ChooseVisitor&); // I've decided to move this into Menu instead (to avoid the repetitions in other classes).
};
struct PurchaseObjectVisitor : public ChooseVisitor, public Object::Visitor {
virtual void visit (Object* object) const {
std::cout << object << " purchased.\n";
}
};
template <typename T>
struct Menu {
struct Option {
T item;
template <typename> void accept (const ChooseVisitor&);
};
Option* option; // Assume Menu<T> with only one option for simplicity here.
template <typename> void choose() const;
void insert (const T& t) {option = new Option{t};}
};
template <typename T>
template <typename Visitor>
void Menu<T>::Option::accept (const ChooseVisitor& visitor) {
// using Type = typename std::remove_pointer<T>::type; // How to cover all possible cases?
const typename Type::Visitor* v = dynamic_cast<const typename Type::Visitor*> (&visitor);
if (v) v->visit(item);
}
template <typename T>
template <typename Visitor>
void Menu<T>::choose() const {
const Visitor visitor;
option->template accept<Visitor>(visitor); // template disambiguator needed.
}
int main() {
Menu<Object*> menu;
menu.insert (new Object);
menu.choose<PurchaseObjectVisitor>();
}
Я начинаю с
template <typename T>
struct GetVisitor {
using type = std::is_pointer<T>::value ? typename std::remove_pointer<T>::type::Visitor : typename T::Visitor;
};
, но он не работает прямо сейчас, а также он должен обрабатывать все возможные типы. Какой самый элегантный способ сделать это? Есть ли простая функция, которая уже делает это?
я обнаружил, что из только сейчас, но мне еще нужно обобщить все другие возможные абсорбции. Я обновил свой вопрос. О, и я верю, что вы знаете, откуда мой вопрос идет от gmbeard (из моего последнего вопроса). Я по-прежнему придерживаюсь вашей идеи, но поскольку различные действия будут происходить в зависимости от того, где используется меню, мне нужно передать разные типы посетителей в функцию select(), чтобы предоставлять разные переопределения для одного и того же типа T для разных ситуации. – prestokeys
Да, ваш другой вопрос определенно является проблемой. Вы вникаете в мутные воды статических гетерогенных контейнеров. Вариант варианта/посетителя кажется единственным способом. – gmbeard