下面我从accept (const ChooseVisitor&);
中取出了Object
函数并将其放在Menu<T>::Option
中,以便只需要在那里调用它而不是那些将要调用的函数拥有accept
功能。唯一的问题是T
可能是一个指针或一个引用,或者其他什么,我需要变成一个没有指针或引用或常量等的常规类型......以获得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;
};
但它现在不能正常工作,而且还需要处理所有可能的类型。最优雅的方式是什么?有没有一个简单的功能呢?
答案 0 :(得分:1)
您错过了::type
。它应该是std::remove_pointer<T>::type
更新:要获得普通类型,您可以嵌套std::remove_
模板 - std::remove_cv<typename std::remove_pointer<typename std:: remove_reference<T>::type>::type>::type