非循环访问者模式。将接受功能移动到一个地方
Acyclic visitor pattern. Moving the accept function to just one place
下面我从 Object
中取出 accept (const ChooseVisitor&);
函数并将其放在 Menu<T>::Option
中,这样它只需要在那里调用而不是许多 类 将具有 accept
功能。唯一的问题是 T
可能是一个指针或引用,或者其他什么,我需要变成一个没有指针或引用或 const 等的常规类型......以获得 T::Visitor*
编译。
#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;
};
但它现在无法正常工作,而且它还需要处理所有可能的类型。最优雅的方法是什么?是否已经有一个简单的函数可以做到这一点?
你失踪了 ::type
。应该是std::remove_pointer<T>::type
更新: 要获得普通类型,您可以嵌套 std::remove_
模板 - std::remove_cv<typename std::remove_pointer<typename std:: remove_reference<T>::type>::type>::type
下面我从 Object
中取出 accept (const ChooseVisitor&);
函数并将其放在 Menu<T>::Option
中,这样它只需要在那里调用而不是许多 类 将具有 accept
功能。唯一的问题是 T
可能是一个指针或引用,或者其他什么,我需要变成一个没有指针或引用或 const 等的常规类型......以获得 T::Visitor*
编译。
#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;
};
但它现在无法正常工作,而且它还需要处理所有可能的类型。最优雅的方法是什么?是否已经有一个简单的函数可以做到这一点?
你失踪了 ::type
。应该是std::remove_pointer<T>::type
更新: 要获得普通类型,您可以嵌套 std::remove_
模板 - std::remove_cv<typename std::remove_pointer<typename std:: remove_reference<T>::type>::type>::type