gpt4 book ai didi

c++ - 类型列表访问者模式示例

转载 作者:行者123 更新时间:2023-11-30 02:09:19 26 4
gpt4 key购买 nike

我对 Typelists 很感兴趣。在这个网址 http://drdobbs.com/184403813有一个很好的例子说明如何使用类型列表创建访问者模式。

关于这个例子我有两个问题。我的两个问题在本主题的末尾。

考虑下面的代码:

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 的说法,这段代码的不便之处在于:

In addition to being thoroughly ugly, the code above has the conceptual problem of being unable to catch at compile time the "forgot to handle this type"

即将到来的类型列表:

    #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 语句。使用类型列表,您只需将新类型添加到类型列表的末尾即可。

类型列表代码可能看起来有很多开销,但您只需编写一次,然后就可以使用它,而不是添加 ifs 或 case 和代码(随着时间的推移它们会变得相当大),您只需添加类型到类型列表。从维护的角度来看,类型列表代码远比一个巨大的 switch 语句或数十或数百个 if 好得多。

至于改进,我不知道,我仍在等待可变参数模板和类型别名包含在 VS 中,以便我可以进一步简化代码。

每当我看到一大堆重复代码时,我就会开始考虑类型列表和元编程,让编译器来完成工作,而不是无聊的程序员。最好的部分是什么?你在运行时得到零惩罚,它和 ifs 一样高效(如果你小心内联)

关于c++ - 类型列表访问者模式示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5578607/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com