访问者Visitor模式:一个作用于某对象结构中的各元素的操作,可用于在不改变各元素的前提下定义作用于这些元素的新操作。
C++11通过可变参数模板,实现一个稳定的接口层,利用可变参数模板的特点,可以让访问者接口层访问任意个数的访问者,不需要每增加一个新的访问者就修改接口层。
#include <iostream>
#include <functional>
#include <string>
using namespace std;
template<typename... Types>
struct Visitor;
template<typename T,typename... Types>
struct Visitor<T,Types...> : Visitor<Types...>
{
using Visitor<Types...>::Visit;
virtual void Visit(const T&)=0;
};
template<typename T>
struct Visitor<T>
{
virtual void Visit(const T&)=0;
};
//测试代码
struct stA;
struct stB;
struct Base
{
/*
自动生成stA和stB的visit虚函数,
struct Visitor<stA,stB>
{
virtual void visit(const stA &)==0;
virtual void visit(const stB &)==0;
}
当被访问者需要增加stC、StD和stE时,只需要定义一个新的类型
typedef Visitor<stA,stB,stC,stD,stE> MytVisitor; 该类型就会自动生成访问接口
struct Visitor<stA,stB,stC,stD,stE>
{
virtual void visit(const stA &)==0;
virtual void visit(const stB &)==0;
virtual void visit(const stC &)==0;
virtual void visit(const stD &)==0;
virtual void visit(const stE &)==0;
}
*/
typedef Visitor<stA,stB> MytVisitor;
virtual void Accept(MytVisitor&)=0;
};
struct stA: Base
{
double val;
void Accept(Base::MytVisitor& v)
{
v.Visit(*this);
}
};
struct stB: Base
{
double val;
void Accept(Base::MytVisitor& v)
{
v.Visit(*this);
}
};
struct PrintVisitor:Base::MytVisitor
{
void Visit(const stA& a)
{
cout<<"from stA: "<<a.val<<endl;
}
void Visit(const stB& b)
{
cout<<"from stB: "<<b.val<<endl;
}
};
int main()
{
PrintVisitor vis;
stA a;
a.val=123.12;
stB b;
b.val=34.56;
Base* base=&a;
base->Accept(vis);
base=&b;
base->Accept(vis);
return 0;
}