时间:2010-02-08 22:55:46

标签: c templates linked-list

刚刚在C中完成了小链表,并意识到我遇到了问题。 C没有模板参数,所以在文件的开头,我声明了我的数据类型列表,如:

typedef int LData;

到目前为止一切顺利,但我不能在一个程序中将这个链表用于2个(或更多个)不同的数据类型。

我可以将LData定义为void*,并根据上下文手动将其转换为特定的数据类型。但我想知道是否有更优雅的解决方案?

5 个答案:

答案 0 :(得分:2)

LData类型定义为void*。链表的用户必须知道它包含哪种数据,因此只要他们将数据输入或输出,他们就可以在void*之间进行转换。

答案 1 :(得分:1)

union是为此目的而发明的,虽然它不是一个非常安全的结构。

答案 2 :(得分:0)

或者,使用不透明指针idiom:

struct datum;
typedef struct datum datum;
typedef datum *LData;

struct datum {
   int whatever;
};

答案 3 :(得分:0)

你可以有一堆#defines定义存储在“link”中的类型吗?

 #define TYPE_INT   0
 #define TYPE_FLOAT 1
 // etc

然后将每个条目定义为:

 struct LinkedListLink
 {
      int    type;
      LData  data;
 };

现在通过检查“类型”,您知道添加了哪种数据(假设您在设置LinkedListLink结构时已正确设置它)。

答案 4 :(得分:0)

当我想使用一组通用链表(或我的情况下,队列)代码时,我将链表指针嵌入到我想要使用它的更大结构中。然后在将参数传递给链表函数时使用链接字段名称。并且有一个函数可以从链接列表指针转换为更大的结构指针,以便从链接列表中获取指针。类似于你在下面看到的代码。

这个习惯用法并没有给你C ++的类型安全性,但是代码非常干净,而且转换只是局限于几个函数。

// some representative bits of my linked list API
//
typedef void* PLINK;

extern PLINK LLAddToList(PLINK head, PLINK new);
extern PLINK LLNextItem(PLINK current); 

// the structure I want to use it with

typedef struct _foo {
   PLINK  pLink;
   int    data1; 
   int    data2;
} FOO;

// to allow for the link pointers to be some other than the first field
// we use this to go from link pointer to structure pointer.
FOO * FooFromPLink(PLINK current) {
    return (FOO *)((char *)&current - FIELD_OFFSET(FOO, pLink));
}

void MyFunction()
{
   // this idiom to use the linklist code with a FOO struct
   //
   FOO * pfoo = // allocate and initialize a foo
   LLAddToList(head, &pfoo->pLink);


   // this idiom to traverse a list of FOOs, etc.
   //
   PLINK next = LLNextItem(head);
   while (next)
      {
      pfoo = FooFromPLink(next);
      // operate on foo.
      next = LLNextItem(next);
      }

}