非循环访问者模式。将接受功能移动到一个地方

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