2009-05-23 45 views
10

我阅读了“Modern C++ Design”中的类型列表,并将其理解为某种类型的联合。通过在类型列表中放入不相关的类型,可以一次表示多个类型,而不需要继承。我使用原始类型在一些简单函数中测试了类型列表,但是我无法让它们中的任何一个工作。如何使用类型列表

有人可以告诉我,如果我的类型列表的unterstanding是正确的,并给一个简单的现实世界的例子如何在每一天平均代码中使用类型列表?提前致谢。

顺便说一句,我使用Windows和Visual Studio 2005及其编译器。

编辑:我的例子不见了,我用VS中的沙箱项目来测试这些东西。但它很安静类似于多布斯教程,代码:

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

这工作,但我没有看到过继承它能够做同样的优势。动态类型转换不适用于原始类型。是否有可能将其作为一个返回值,如:

typedef Typelist<int, string> mylist 
mylist myfunction() { 
    if(foo == bar) 
     return 5; 

    return "five"; 
} 
+0

添加一个不适用于您的问题的代码示例。 – 2009-05-23 16:54:57

回答

18

类型列表是类型的通用编译时间集合。如果你使用dynamic_cast,你就错过了这一点,因为它不应该被需要,因为它是一个静态的编译时间概念。

这有效,但我没有看到优于继承能够做到这一点。

你不能让任何现有的类型继承你想要的任何东西。这根本不可行,因为这种现有类型可能是内置类型或库中的类型。 把类型列表看作是类型列表的扩展(例如在std :: pair中),对于任何合理数量的类型(而不是2)。

类型列表可用于创建一个工具来将一组参数传递给一个函数。这是一段代码,其中包含5个参数(来自Modern C++设计的另一个概念)的广义仿函数,其中包含一个tupe(又一个)参数,该类型列表定义元组中保存的对象类型:

//functor is just a holder of a pointer to method and a pointer to object to call this 
//method on; (in case you are unfamiliar with a concept) 
template<class R, class t0, class t1, class t2, class t3, class t4> 
R call(Loki::Functor<R,LOKI_TYPELIST_5(t0, t1, t2, t3, t4 
    )> func, 
    Loki::Tuple<LOKI_TYPELIST_5(t0, t1, t2, t3, t4)> tuple) 
{ 
    ///note how you access fields 
    return func(Loki::Field<0>(tuple), Loki::Field<1>(tuple), 
     Loki::Field<2>(tuple), Loki::Field<3>(tuple), 
     Loki::Field<4>(tuple)); 
} 

//this uses the example code 
#include<iostream> 
using namespace std; 

int foo(ostream* c,int h,float z, string s,int g) 
{ 
    (*c)<<h<<z<<s<<g<<endl; 
    return h+1 
} 

int main(int argc,char**argv) 
{ 
    Loki::Functor<int,LOKI_TYPELIST_5(ostream*, int, float, string, int)> f=foo; 
    //(...) 
    //pass functor f around 
    //(...) 
    //create a set of arguments 
    Loki::Tuple<LOKI_TYPELIST_5(ostream*, int, float, string, int)> tu; 
    Field<0>(tu)=&cout; 
    Field<1>(tu)=5; 
    Field<2>(tu)=0.9; 
    Field<3>(tu)=string("blahblah"); 
    Field<4>(tu)=77; 
    //(...) 
    //pass tuple tu around, possibly save it in a data structure or make many 
    //specialized copies of it, or just create a memento of a call, such that 
    //you can make "undo" in your application; note that without the typelist 
    //you would need to create a struct type to store any set of arguments; 
    //(...) 
    //call functor f with the tuple tu 
    call(f,tu); 
} 

请注意,只有类似于元组或函数的其他概念,类型列表才会开始有用。 另外,我在一个项目中遇到了Loki大约2年,并且由于模板代码(很多),DEBUG版本中的可执行文件的大小往往很大(我的记录大小为35 MB左右)。编译速度也有所下降。还记得C++ 0x可能会包含一些等价的机制。结论:如果您不需要,尽量不要使用类型列表。

+0

非常感谢,你为我清除了一些东西。我想我应该再读一遍这一章。 – DaClown 2009-05-24 07:55:10

5

是否从博士道博的日记帮助任何this文章?

4

类型列表是将“参数列表”传递给作为编译过程一部分“执行”的模板元程序的一种方式。

因此,它们可以用于生成某种“联合”类型,但这只是一种可能的用途。

对于“真实世界”示例:在Comet库中实现COM对象时,我们使用类型列表来自动生成“QueryInterface”方法。

它允许你写这样的代码:

class Dog : public implement_qi<make_list<IAnimal, INoisy, IPersistStream> > 
{ 
    // The implement_qi template has provided 
    // an implementation of COM's QueryInterface method for us without 
    // having to write an ugly ATL "message map" or use any Macros. 
    ... 
} 

在这个例子中,“make_list”是用来生成一个“类型列表”,其中implement_qi模板然后可以“枚举”为模板generate the appropriate QueryInterface code