在c仿真模板 [英] Simulation of templates in C

查看:111
本文介绍了在c仿真模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用我的C.实施是非常简单的实施队列结构;队列只能容纳 INT 和没有别的。我在想,如果我能在 C 模拟 C ++ 模板(可能通过使用preprocessor ​​的#define ),使我的队列可以保存任何数据类型。

I' m trying to implement a queue structure using C. My implementation is very simple; the queue can hold only ints and nothing else. I was wondering if I could simulate C++ templates in C(probably by using the preprocessor #define) so that my queue can hold any data type.

注意:我不想用无效* 。我认为这是一个有点冒险,很容易导致怪异的运行时错误。

Note: I do not want to use void*. I think it is a bit risky and can easily cause bizarre runtime errors.

推荐答案

您可以为了营造那种模板使用微妙的和丑陋的技巧。这是我会做:

You can use subtle and ugly tricks in order to create that kind of templates. Here's what I would do:

我首先创建一个宏 - 姑且称之为说 define_list(类型) - 这将创造一切功能,给定类型的列表。然后我会创建一个包含函数指针的所有列表的功能,一个全球性的结构,然后有一个指针列表中的每个实例,全球结构(注意这是一个的虚方法表)。这种事情:

I would first create a macro - let's call it say define_list(type) - that would create all the functions for a list of a given type. I would then create a global structure containing function pointers to all the list's functions and then have a pointer to that global structure in each instance of the list (note how similar it is to a virtual method table). This kind of thing:

#define define_list(type) \
\
    struct _list_##type; \
    \
    typedef struct \
    { \
        int (*is_empty)(const struct _list_##type*); \
        size_t (*size)(const struct _list_##type*); \
        const type (*front)(const struct _list_##type*); \
        void (*push_front)(struct _list_##type*, type); \
    } _list_functions_##type; \
    \
    typedef struct _list_elem_##type \
    { \
        type _data; \
        struct _list_elem_##type* _next; \
    } list_elem_##type; \
    \
    typedef struct _list_##type \
    { \
        size_t _size; \
        list_elem_##type* _first; \
        list_elem_##type* _last; \
        _list_functions_##type* _functions; \
    } List_##type; \
    \
    List_##type* new_list_##type(); \
    bool list_is_empty_##type(const List_##type* list); \
    size_t list_size_##type(const List_##type* list); \
    const type list_front_##type(const List_##type* list); \
    void list_push_front_##type(List_##type* list, type elem); \
    \
    bool list_is_empty_##type(const List_##type* list) \
    { \
        return list->_size == 0; \
    } \
    \
    size_t list_size_##type(const List_##type* list) \
    { \
        return list->_size; \
    } \
    \
    const type list_front_##type(const List_##type* list) \
    { \
        return list->_first->_data; \
    } \
    \
    void list_push_front_##type(List_##type* list, type elem) \
    { \
        ... \
    } \
    \
    _list_functions_##type _list_funcs_##type = { \
        &list_is_empty_##type, \
        &list_size_##type, \
        &list_front_##type, \
        &list_push_front_##type, \
    }; \
    \
    List_##type* new_list_##type() \
    { \
        List_##type* res = (List_##type*) malloc(sizeof(List_##type)); \
        res->_size = 0; \
        res->_first = NULL; \
        res->_functions = &_list_funcs_##type; \
        return res; \
    }

#define List(type) \
    List_##type

#define new_list(type) \
    new_list_##type()

通用接口

下面是一些宏,只需通过存储函数指针调用列表的功能:

Generic interface

Here are some macros that simply call the list's functions via the stored function pointers:

#define is_empty(collection) \
    collection->_functions->is_empty(collection)

#define size(collection) \
    collection->_functions->size(collection)

#define front(collection) \
    collection->_functions->front(collection)

#define push_front(collection, elem) \
    collection->_functions->push_front(collection, elem)

请注意,如果使用相同的结构设计其他收藏品比列表,您可以使用最后一个功能为存储好的指针的集合。

Note that if you use the same structure to design other collections than lists, you'll be able to use the last functions for any collections that stores the good pointers.

和结束,如何使用我们新的列表模板的一个小例子:

And to conclude, a small example of how to use our new list template:

/* Define the data structures you need */
define_list(int)
define_list(float)

int main()
{
    List(int)* a = new_list(int);
    List(float)* b = new_list(float);

    push_front(a, 5);
    push_front(b, 5.2);
}

您可以使用技巧的量,如果你真的想有某种用C模板,但这是相当丑陋(只使用C ++,它会更简单)。唯一的开销将是每个数据结构的情况下多了一个指针,因此多了一个间接每当你调用一个函数(不投完成后,你不必存储无效* 指针,是\\ O /)。希望你永远不会使用:P

You can use that amount of tricks if you really want to have some kind of templates in C, but that's rather ugly (just use C++, it'll be simpler). The only overhead will be one more pointer per instance of data structure, and thus one more indirection whenever you call a function (no cast is done, you don't have to store void* pointers, yeah \o/). Hope you won't ever use that :p

当然也有一定的局限性,因为我们使用的是单纯的文本替换宏,而不是真正的模板。

There are of course some limitations since we are using mere text replacement macros, and not real templates.

您只能定义每种类型每个编译单元一次,否则,你的程序将无法编译。这可以是例如一个重大的缺点,如果你写一个图书馆和一些你的头包含一些定义_ 的说明。

You can only define each type once per compile unit, otherwise, your program will fail to compile. This can be a major drawback for example if you write a library and some of your headers contain some define_ instructions.

如果你想创建一个列表的模板类型是由几个单词(符号字符无符号长常量栏结构美孚 ...)或其模板类型为指针(的char * 无效* ...),你将不得不的typedef 这种类型的第一位。

If you want to create a List whose template type is made of several words (signed char, unsigned long, const bar, struct foo...) or whose template type is a pointer (char*, void*...), you will have to typedef that type first.

define_list(int) /* OK */
define_list(char*) /* Error: pointer */
define_list(unsigned long) /* Error: several words */

typedef char* char_ptr;
typedef unsigned long ulong;
define_list(char_ptr) /* OK */
define_list(ulong) /* OK */

您将不得不诉诸同样的伎俩,如果你想创建嵌套列表。

You will have to resort to the same trick if you want to create nested lists.

这篇关于在c仿真模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆