2010-06-12 69 views
2

阅读计算器的一些例子,以下为一些我以前的问题的答案(1)后,我最终得出了“战略”这个。“模仿”C++模板的C策略是什么?

我已经来到这个:

1)已经在.h文件声明段。在这里我将定义数据结构和访问接口。例如:

/** 
* LIST DECLARATION. (DOUBLE LINKED LIST) 
*/ 
#define NM_TEMPLATE_DECLARE_LIST(type) \ 
typedef struct nm_list_elem_##type##_s { \ 
    type data; \ 
    struct nm_list_elem_##type##_s *next; \ 
    struct nm_list_elem_##type##_s *prev; \ 
} nm_list_elem_##type ; \ 
typedef struct nm_list_##type##_s { \ 
    unsigned int size; \ 
    nm_list_elem_##type *head; \ 
    nm_list_elem_##type *tail; \ 
    int (*cmp)(const type e1, const type e2); \ 
} nm_list_##type ; \ 
\ 
nm_list_##type *nm_list_new_##type##_(int (*cmp)(const type e1, \ 
    const type e2)); \ 
\ 
(...other functions ...) 

2)裹中相应的界面中宏功能:

/** 
* LIST INTERFACE 
*/ 
#define nm_list(type) \ 
    nm_list_##type 

#define nm_list_elem(type) \ 
    nm_list_elem_##type 

#define nm_list_new(type,cmp) \ 
    nm_list_new_##type##_(cmp) 

#define nm_list_delete(type, list, dst) \ 
    nm_list_delete_##type##_(list, dst) 

#define nm_list_ins_next(type,list, elem, data) \ 
    nm_list_ins_next_##type##_(list, elem, data) 

(...others...) 

3)实现以下功能:

/** 
* LIST FUNCTION DEFINITIONS 
*/ 
#define NM_TEMPLATE_DEFINE_LIST(type) \ 
nm_list_##type *nm_list_new_##type##_(int (*cmp)(const type e1, \ 
    const type e2)) \ 
{\ 
    nm_list_##type *list = NULL; \ 
    list = nm_alloc(sizeof(*list)); \ 
    list->size = 0; \ 
    list->head = NULL; \ 
    list->tail = NULL; \ 
    list->cmp = cmp; \ 
}\ 
void nm_list_delete_##type##_(nm_list_##type *list, \ 
    void (*destructor)(nm_list_elem_##type elem)) \ 
{ \ 
    type data; \ 
    while(nm_list_size(list)){ \ 
     data = nm_list_rem_##type(list, tail); \ 
     if(destructor){ \ 
      destructor(data); \ 
     } \ 
    } \ 
    nm_free(list); \ 
} \ 
(...others...) 

为了使用那些结构,我要创建两个文件(姑且称之为templates.ctemplates.h)。

templates.h我将不得不NM_TEMPLATE_DECLARE_LIST(int)NM_TEMPLATE_DECLARE_LIST(double),而在templates.c我需要NM_TEMPLATE_DEFINE_LIST(int)NM_TEMPLATE_DEFINE_LIST(double),才能有后面的整数,双打等,生成列表的代码。

通过遵循这个策略,我将不得不将所有的“模板”声明保留在两个文件中,并且在需要数据结构的同时,我需要包含templates.h。这是一个非常“集中”的解决方案。

你才能知道其他策略,以“模拟”(在某一时刻)的C++模板?你知道的方式来改善这一战略,以保持更分散的方式的东西,所以我不会需要两个文件:templates.ctemplates.h

+1

你可以实现一种支持C语言模板的语言; 虽然我不知道另一种方法,但我认为合适,但几乎每个人都可以完成这一任务模式,当他们确实需要模板时,从我的经验。 – jer 2010-06-12 21:08:21

+0

我想使用C++将是不可能的? – 2010-06-12 21:21:36

+0

是的,C++是不可能的。 – 2010-06-12 21:22:47

回答

1

你举的例子只是模板的许多可能的用途之一 - 生成一个通用的数据结构。这个例子不需要任何使模板强大的推理;要求一些可以让你创建通用数据结构的东西并不是要求相当于C++模板的东西。

一些用于<tgmath.h>可能会给一些类型推理能力实现技术,但他们仍然是弱得多,比C++模板的移植性较差。

对于容器的具体示例,我不打扰 - 只需在其中创建一个带有void *数据的列表,并使用malloc和free来创建数据,或者让列表有一对函数指针创造和摧毁价值。您也可以仅依靠客户端来管理数据,而不是将该值作为列表的成员。如果要保存间接寻址,请使用可变长度数组作为数据成员。由于C不像C++那样类型安全,因此拥有void *数据不是问题。

你可以做一些复杂的代码生成与宏,但也有其他工具来生成代码。就我个人而言,我喜欢使用XSLT进行代码生成,但是您的构建过程完全没有类似C的部分。

1

保存自己的一些麻烦和利用现有queue(3)组宏 - 久经考验,在内核源代码中使用等

2

我可能不应该承认这样做,但是当我需要的“模板化”在过去丙地的容器,我写的“模板化的队列班”为一对特殊的文件,如:

文件MyQueue.include_h:

/** NOTE: THIS IS NOT a REAL .h FILE, it only looks like one! Don't #include it! */ 
struct MyQueueClass 
{ 
    void init_queue(MyQueueClass * q); 
    void push_back(MyQueueClass * q, MyQueueClassItem * item); 

    [....All the other standard queue header declarations would go here....] 

    MyQueueClassItem * _head; 
    MyQueueClassItem * _tail; 
    int _size; 
}; 

文件MyQueue.include_c:

/** NOTE: THIS IS NOT A REAL .c FILE, it only looks like one! Don't compile directly! */ 
void init_queue(MyQueueClass * q) 
{ 
    q->_size = 0; 
    q->_head = q->_tail = NULL; 
} 

void push_back(MyQueueClass * q, MyQueueClassItem * item) 
{ 
    if (q->_head == NULL) q->_head = q->_tail = item; 
    else 
    { 
     q->_tail->_next = item; 
     item->_prev = q->_tail; 
     q->_tail = item; 
    } 
    q->_size++; 
} 

[....All the other standard queue function bodies would go here....] 

然后,每当我想 “实例” 我的队列 “模板” 使用一个特定的项目,典型值E,我把这样的事情为实际的.c和.h文件:

在我真正的.h文件之一:

#define MyQueueClass struct SomeSpecificQueueType 
#define MyQueueClassItem struct SomeSpecificQueueTypeItem 
# include "MyQueue.include_h" 
#undef MyQueueClassItem 
#undef MyQueueClass 

在我真正的.c文件一个(它不“T无论哪一个):

#define MyQueueClass struct SomeSpecificQueueType 
#define MyQueueClassItem struct SomeSpecificQueueTypeItem 
# include "MyQueue.include_c" 
#undef MyQueueClass 
#undef MyQueueClassItem 

....和急,C预处理器作为一个穷人的模板扩展,而无需完整的‘模板定义’被开出了巨大的#define的声明。

+2

它不允许在一个文件中声明两个持有不同类型值的队列 - 函数名称会冲突。 – 2010-06-12 23:43:48