c++ - 使用 C++ 模板实现访问者模式

标签 c++ templates visitor-pattern

我一直在尝试通过使用 C++ 模板来实现访问者模式来减少代码中的样板数量。到目前为止,我想出了这个:

class BaseVisitor {
public:
    virtual ~BaseVisitor() {}
};

template<typename T>
class Visitor : public BaseVisitor {
public:
    virtual void visit(T& /* visitable */) = 0;
};

template<typename Derived>
class Visitable {
public:
    void accept(Visitor<Derived>& visitor) {
        visitor.visit(static_cast<Derived&>(*this));
    }
};

Visitable 的每个子类如下所示:

class Mesh : public Object, public Visitable<Mesh> {};
class Text : public Object, public Visitable<Text> {};

最后游客看起来像这样:

class Renderer : public Visitor<Mesh>, public Visitor<Text> {}

到目前为止一切都很好......现在问题来了:

for(Scene::iterator it = scene.begin(); it != scene.end(); ++it) {
    Object& object = static_cast<Object&>(*it);
    if(pre_visit(object)) {
        object.accept(this); ///Erm, what do I cast to??
        post_visit(object);
    }
}

我需要以某种方式转换为 Visitable,以便我可以调用 accept(),但显然我不知道 T 是什么。或者,我无法将虚拟 accept() 添加到 Visitable 模板,因为我不知道它应该采用什么参数。

有任何 C++ 模板大师知道如何完成这项工作吗?

最佳答案

这可以在 C++11 中使用可变参数模板来完成。继续皮特的回答:

// Visitor template declaration
template<typename... Types>
class Visitor;

// specialization for single type    
template<typename T>
class Visitor<T> {
public:
    virtual void visit(T & visitable) = 0;
};

// specialization for multiple types
template<typename T, typename... Types>
class Visitor<T, Types...> : public Visitor<Types...> {
public:
    // promote the function(s) from the base class
    using Visitor<Types...>::visit;

    virtual void visit(T & visitable) = 0;
};

template<typename... Types>
class Visitable {
public:
    virtual void accept(Visitor<Types...>& visitor) = 0;
};

template<typename Derived, typename... Types>
class VisitableImpl : public Visitable<Types...> {
public:
    virtual void accept(Visitor<Types...>& visitor) {
        visitor.visit(static_cast<Derived&>(*this));
    }
};

Visitable 的子类:

class Mesh : public Object, public VisitableImpl<Mesh, Mesh, Text> {};
class Text : public Object, public VisitableImpl<Text, Mesh, Text> {};

一个 Visitor子类:

class Renderer : public Visitor<Mesh, Text> {};

不清楚 value_type 是什么您的Scene容器是,但您需要获得指向 Visitable<Mesh, Text> 的引用或指针调用accept :

for(Scene::iterator it = scene.begin(); it != scene.end(); ++it) {
    Visitable<Mesh, Text>& object = static_cast<Visitable<Mesh, Text>&>(*it);
    if(pre_visit(object)) {
        object.accept(*this);
        post_visit(object);
    }
}

关于c++ - 使用 C++ 模板实现访问者模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11796121/

相关文章:

c++ - 使用 std::array<T, N> 会导致代码膨胀吗?

c++ - 是否可以回调模板类的成员?

用于测试 AST 访问者的 Java 源代码

c++ - 任务管理器的精确度如何?

c++ - 有 C++ 的 LINQ 库吗?

c++ - 模板类实例接收不同类型的同一模板类的另一个实例

c++ - 什么更快 : down-cast from virtual base or cross-cast?

java - 父类和子类之间的多态性

c++ - 可以将 &my_boost_array_variable[2] 传递给期望 void* 的 C 函数吗?

java - 是否有查询 HTML 表的 SQL 包装器