非循环访客模式.将接受函数移动到一个位置

Acyclic visitor pattern. Moving the accept function to just one place

本文关键字:位置 一个 移动 函数 访客 循环 模式      更新时间:2023-10-16

下面我从Object中取出了accept (const ChooseVisitor&);函数并将其放在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;
};

但它现在不起作用,而且它需要处理所有可能的类型。 最优雅的方法是什么? 有没有一个简单的功能已经这样做了?

你错过了::type .应该是std::remove_pointer<T>::type

更新:要获得纯类型,您可以嵌套std::remove_模板 - std::remove_cv<typename std::remove_pointer<typename std:: remove_reference<T>::type>::type>::type