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

Implementing the visitor pattern using C++ Templates(使用 C++ 模板实现访问者模式)
本文介绍了使用 C++ 模板实现访问者模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

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

I've been trying to reduce the amount of boilerplate in my code, by using C++ Templates to implement the visitor pattern. So far I've come up with this:

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));
    }
};

Visible 的每个子类如下所示:

And each subclass of Visitable looks like this:

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

最后访问者看起来像这样:

And finally the Visitor looks like this:

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

到目前为止一切顺利……现在问题来了:

So far so good... now here's the problem:

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 是什么.或者,我无法向 Visitable 模板添加虚拟 accept(),因为我不知道它应该采用什么参数.

I need to somehow cast to Visitable so that I can call accept(), but obviously I don't know what T is. Alternatively I can't add a virtual accept() to the Visitable template, because I don't know what argument it should take.

任何 C++ 模板大师都知道如何使这个工作?

Any C++ Templating guru's out there know how to make this work?

推荐答案

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

This can be done in C++11 using variadic templates. Continuing from Pete's answer:

// 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> {};

不清楚你的 Scene 容器的 value_type 是什么,但你需要获得一个引用或指向 Visitable 调用accept:

It's not clear what the value_type of your Scene container is but you need to obtain a reference or pointer to Visitable<Mesh, Text> on which to call 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++ 模板实现访问者模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

How do compilers treat variable length arrays(编译器如何处理变长数组)
Deduce template argument from std::function call signature(从 std::function 调用签名推导出模板参数)
check if member exists using enable_if(使用 enable_if 检查成员是否存在)
Standard Library Containers with additional optional template parameters?(具有附加可选模板参数的标准库容器?)
Uses of a C++ Arithmetic Promotion Header(C++ 算术提升标头的使用)
Parameter pack must be at the end of the parameter list... When and why?(参数包必须位于参数列表的末尾...何时以及为什么?)