打字员访问模式示例
Typelists visitor pattern example
我喜欢打字员。在此url://drdobbs.com/184403813有一个很好的例子,说明如何使用typelist来创建访问者模式。
关于这个例子,我有两个问题。我的两个问题在这个话题的最后。考虑以下代码:
void SomeOperation(DocumentItem* p)
{
if (TextArea* pTextArea = dynamic_cast<TextArea*>(p))
{
... operate on a TextArea object ...
}
else if (VectorGraphics* pVectorGraphics =
dynamic_cast<VectorGraphics*>(p))
{
... operate on a VectorGraphics object ...
}
else if (Bitmap* pBitmap = dynamic_cast<Bitmap*>(p))
{
... operate on a Bitmap object ...
}
else
{
throw "Unknown type passed";
}
}
根据Alexandrescu的说法,这个代码的不便之处是:
除了非常丑陋之外,上面的代码还有一个概念性问题,即无法在编译时捕获"忘记处理此类型"
未来的打字员也是如此:
#include<iostream>
class null_typelist {};
template <class H, class T>
struct typelist
{
typedef H head;
typedef T tail;
};
template<class T1, class T2=null_typelist, class T3=null_typelist, class T4=null_typelist> struct cons;
template <class T1>
struct cons<T1, null_typelist, null_typelist,null_typelist>
{
typedef typelist<T1, null_typelist> type;
};
template <class T1, class T2>
struct cons<T1, T2, null_typelist, null_typelist>
{
typedef typelist<T1, typelist<T2,null_typelist> > type;
};
template <class T1, class T2, class T3>
struct cons<T1, T2, T3, null_typelist>
{
typedef typelist<T1, typelist<T2, typelist<T3,null_typelist> > > type;
};
template <class T1, class T2, class T3, class T4>
struct cons
{
typedef typelist<T1, typelist<T2, typelist<T3,typelist<T4, null_typelist> > > > type;
};
template <class tlist> class AdHocVisitor;
template <class H, class T>
class AdHocVisitor< typelist<H, T> > : public AdHocVisitor<T>
{
public:
virtual void Visit(H*) = 0;
template <class SomeClass>
void StartVisit(SomeClass* p)
{
if (H* pFound = dynamic_cast<H*>(p))
{
Visit(pFound);
}
else
{
AdHocVisitor<T>::StartVisit(p);
}
}
};
template <class H>
class AdHocVisitor< typelist<H, null_typelist> >
{
public:
virtual void Visit(H*) = 0;
template <class SomeClass>
void StartVisit(SomeClass* p)
{
if (H* pFound = dynamic_cast<H*>(p))
{
Visit(pFound);
}
else
{
throw "Unknown type passed";
}
}
};
struct DocElement{virtual ~DocElement(){};};
struct TextArea: DocElement{};
struct Bitmap: DocElement{};
struct VectorGraphics: DocElement{};
int main()
{
typedef cons<TextArea,Bitmap,VectorGraphics>::type MyHierarchy;
DocElement *p = new Bitmap;
struct ConcreteVisitor : AdHocVisitor<MyHierarchy>
{
void Visit(TextArea* p){std::cout << "I'm a textarea" << "n";}
void Visit(VectorGraphics* p){std::cout << "I'm a VectorGraphics" << "n";}
void Visit(Bitmap* p){std::cout << "I'm a Bitmap" << "n";}
};
ConcreteVisitor visitor;
visitor.StartVisit(p);
delete p;
std::cin.get();
}
1-仍然有dynamic_cast和虚函数。所以我看不出引进打字员有什么好处?
2-在这篇文章的最后Alexandrescu给出了一些建议,以改进这段代码,但我不太清楚如何实现这些,有人可以帮助我吗?
谢谢
如果你有50个DocElement类型呢?在第一个示例中,您需要50个if语句,而在第二个示例中,您只需要一个包含50个元素的类型列表。
您还可以考虑添加另一个DocElement时会发生什么。在第一个示例中,您需要修改if-else语句。使用类型列表,你可以将新类型添加到类型列表的末尾。
类型列表代码可能看起来开销很大,但是您只编写一次,然后使用它,而不是添加if或case和代码(随着时间的推移可能会变得相当大),您只需向类型列表添加类型。从维护的角度来看,类型列表代码远比一个巨大的switch语句或几十个或几百个if要好得多。
至于改进,我不知道,我仍然在等待可变模板和类型别名包含在VS中,以便我可以进一步简化代码。
每当我看到一大堆重复的代码时,我就开始考虑类型列表和元编程,让编译器来做这些工作,而不是无聊的程序员。最好的部分是什么?在运行时你不会受到任何惩罚,它和if一样有效(如果你小心使用内联)
相关文章:
- 用于在并发环境中访问 MMIO 的软件模式
- 针对跨模式访问的 SIMD 优化
- D 指针/pimpl 模式基类指针访问派生类成员
- 使用访问者设计模式在N- ARY树中重复访问子节点值
- 为什么在发布模式下无法访问 for 循环,但在调试中它工作正常
- 在DEBUG模式下调整字节字段大小时发生访问冲突
- 我需要在我的设计中访问模式吗?
- 如何在Meyers Singleton模式中访问衍生的构造函数
- 从用户应用程序访问环0模式(以及Borland允许这样做的原因)
- 使用自定义模式进行序列化,并使用Boost进行随机访问
- 数据库访问对象设计模式
- Windows高速模式(C++):等待信号量(WaitForSingleObjectEx):失败,访问被拒绝[部分解决]
- scoped_lock访问资源的优雅模式
- 具有多个可访问参数的C++访客模式
- 如何优化间接基数排序?(又名如何优化不可预测的内存访问模式)
- 用于独立访问器/赋值器接口的C++设计模式
- 用于通过常量中介访问非常量的设计模式
- SQLite C++多个进程以只读模式访问数据库时"数据库已锁定"
- 在哪里存储Visitor模式中访问的每个元素的计算结果
- 如何在用户模式应用程序C++中访问AVStream扩展相机控制属性