使用带有模板派生类的访问者模式 [英] Using the Visitor Pattern with template derived classes

查看:147
本文介绍了使用带有模板派生类的访问者模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用模板派生类实现访问者模式

I try to implement the Visitor pattern with templated derived classes

这里是VisitorTemplate.hpp,我在类Visitor中专门的Derived,但我想能够处理任何类型:

here is the VisitorTemplate.hpp, I specialized Derived in the class Visitor, but I'd like to be able to handle any type:

:感谢interjay的建议,代码编译和运行没有错误现在

edit : thanks to the suggestions of interjay, the code compiles and runs without errors now

#ifndef VISITORTEMPLATE_HPP_
#define VISITORTEMPLATE_HPP_

#include <iostream>
#include <string>
using namespace std;

template<class T> Derived;

class Visitor
{
  public:
    virtual void visit(Derived<string> *e) = 0;
};

class Base
{
  public:
    virtual void accept(class Visitor *v) = 0;
};

template<class T>
Derived: public Base
{
  public:
    virtual void accept(Visitor *v)
    {
       v->visit(this);
    }
    string display(T arg)
    {
       string s = "This is : " + to_string(arg);
       return s;
    }
};

class UpVisitor: public Visitor
{
   virtual void visit(Derived<string> *e)
   {
     cout << "do Up on " + e->display("test") << '\n';
   }
};

class DownVisitor: public Visitor
{
   virtual void visit(Derived<string> *e)
   {
     cout << "do Down on " + e->display("test") << '\n';
   }
};

#endif /* VISITORTEMPLATE_HPP_ */

main.cpp

Base* base = new Derived<string>();
Visitor* up = new UpVisitor();
Visitor* down = new DownVisitor();
base->accept(up);
base->accept(down);

现在我的目标是在没有专业的情况下使用Derived不幸的是,visit是一个虚方法,所以我不能模板它

Now my goal is to use Derived in visit without specializing; unfortunately, visit is a virtual method so I can't template it

推荐答案

从现代C ++ - 设计通用编程和设计模式 - Andrei Alexandrescu

From Modern C++ - Design Generic Programming and Design Patterns Applied - Andrei Alexandrescu

#include <iostream>

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

template <class T, typename R = int>
class Visitor
{
    public:
        virtual R visit(T &) = 0;
};

template <typename R = int>
class BaseVisitable
{
    public:
        typedef R ReturnType;
        virtual ~BaseVisitable() {};
        virtual ReturnType accept(BaseVisitor & )
        {
            return ReturnType(0);
        }
    protected:
        template <class T>
        static ReturnType acceptVisitor(T &visited, BaseVisitor &visitor)
        {
            if (Visitor<T> *p = dynamic_cast< Visitor<T> *> (&visitor))
            {
                return p->visit(visited);
            }
            return ReturnType(-1);
        }

        #define VISITABLE() \
            virtual ReturnType accept(BaseVisitor &v) \
                { return acceptVisitor(*this, v); }
};


/** example of use */
class Visitable1 : public BaseVisitable<int>
{
    /* Visitable accept one BaseVisitor */
    public:
        VISITABLE();
};

class Visitable2 : public BaseVisitable<int>
{
    /* Visitable accept one BaseVisitor */
    public:
        VISITABLE();
};

class VisitorDerived : public BaseVisitor,
        public Visitor<Visitable1, int>,
        public Visitor<Visitable2, int>
{
    public:
        int visit(Visitable1 & c)
        {
            std::cout << __PRETTY_FUNCTION__ << std::endl;
        }
        int visit(Visitable2 & c)
        {
            std::cout << __PRETTY_FUNCTION__ << std::endl;
        }
};

int main(int argc, char **argv)
{
    VisitorDerived visitor;
    Visitable1 visitable1;
    Visitable2 visitable2;

    visitable1.accept(visitor);
    visitable2.accept(visitor);
}

可以避免使用CRTP模式的dynamic_cast:

Is possible to avoid dynamic_cast with CRTP pattern like:

#include <iostream>

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

template <class T>
class Visitor
{
    public:
        virtual void visit(T &) = 0;
};

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

/** example of use */
class Visitable1 : public BaseVisitable<Visitable1>
{
};

class Visitable2 : public BaseVisitable<Visitable2>
{
};

class VisitorDerived : public BaseVisitor, 
                       public Visitor<Visitable1>,
                       public Visitor<Visitable2>
{
    public:
        void visit(Visitable1 & c)
        {
            std::cout << __PRETTY_FUNCTION__ << std::endl;
        }
        void visit(Visitable2 & c)
        {
            std::cout << __PRETTY_FUNCTION__ << std::endl;
        }
};

int main(int argc, char **argv)
{
    VisitorDerived visitor;
    Visitable1 visitable1;
    Visitable2 visitable2;

    visitable1.accept<VisitorDerived>(visitor);
    visitable2.accept<VisitorDerived>(visitor);
}

这篇关于使用带有模板派生类的访问者模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆