【问题标题】:Trying to make templates in C尝试在 C 中制作模板
【发布时间】:2015-03-10 21:07:45
【问题描述】:

我使用宏在 C 中创建了一个通用向量。这个概念是否可行,或者我是否会因为想一想而单程前往篝火?

#ifndef VECTOR_H
#define VECTOR_H

#define vector_at(vector, pos) ((vector).data[pos])

#define VECTOR_DEFINITION(type)\
typedef struct {\
    size_t size;\
    size_t capacity;\
    type *data;\
} vector_ ## type ## _t;\
void vector_ ## type ## _reserve(vector_ ## type ## _t *vector, size_t size) {\
    size_t capacity = 1;\
    while (capacity < size) capacity *= 2;\
    if (size == 0) capacity = 0;\
    if (capacity != vector->capacity)\
    {\
        vector->capacity = capacity;\
        if (size == 0) {\
            free(vector->data);\
            vector->data = NULL;\
        } else {\
            vector->data = realloc(vector->data, vector->capacity * sizeof(type));\
        }\
    }\
}\
void vector_ ## type ## _resize(vector_ ## type ## _t *vector, size_t size) {\
    vector->size = size;\
    vector_ ## type ## _reserve(vector, size);\
}\
void vector_ ## type ## _push_back(vector_ ## type ## _t *vector, type value) {\
    if (vector->size >= vector->capacity) {\
        if (vector->capacity == 0) vector->capacity = 1;\
        else vector->capacity *= 2;\
        vector->data = realloc(vector->data, vector->capacity * sizeof(type));\
    }\
    vector->data[vector->size++] = value;\
}\
type vector_ ## type ## _pop_back(vector_ ## type ## _t *vector) {\
    return vector->data[--vector->size];\
}\
void vector_ ## type ## _init(vector_ ## type ## _t *vector, size_t size) {\
    vector->size = size;\
    vector->capacity = 0;\
    vector->data = NULL;\
    vector_ ## type ## _reserve(vector, size);\
}\
void vector_ ## type ## _destroy(vector_ ## type ## _t *vector) {\
    free(vector->data);\
    vector->size = 0;\
    vector->capacity = 0;\
    vector->data = NULL;\
}\

#endif

然后可以像这样使用代码:

#include <stdio.h>
#include <stdlib.h>
#include "vector.h"

typedef unsigned int uint;
typedef char* str;

VECTOR_DEFINITION(uint)
VECTOR_DEFINITION(str)

int main()
{
    vector_uint_t vector;
    vector_uint_init(&vector, 10);

    for (unsigned int i = 0; i < vector.size; ++i)
        vector.data[i] = i;

    for (unsigned int i = 0; i < 10; ++i)
        vector_uint_push_back(&vector, i);

    for (unsigned int i = 0; i < vector.size; ++i)
        printf("%d ", vector.data[i]);
    printf("\n");

    vector_uint_destroy(&vector);

    vector_str_t sentence;
    vector_str_init(&sentence, 0);

    vector_str_push_back(&sentence, "Hello");
    vector_str_push_back(&sentence, "World!");
    vector_str_push_back(&sentence, "How");
    vector_str_push_back(&sentence, "are");
    vector_str_push_back(&sentence, "you?");

    for (unsigned int i = 0; i < sentence.size; ++i)
        printf("%s ", sentence.data[i]);
    printf("\n");

    vector_str_destroy(&sentence);

    return 0;
}

并产生以下输出:

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 
Hello World! How are you? 

此外,是否有更好的方法来实现具有类型安全性的通用容器?

【问题讨论】:

  • 如果有人将VECTOR_DEFINITION(uint) 放在源代码的两个不同位置会发生什么?
  • 我认为代码不会编译,因为定义会被重复两次。我不能使用 ifdef 技巧来防止这种情况,因为宏会在调用定义之前展开。现在我想了想,我应该为头文件和源文件制作两个定义宏,以便程序员可以在单个头文件/源文件中定义容器以满足他们的需求。
  • 已经有一些其他的 QA 对此主题进行了有趣的讨论,例如:stackoverflow.com/questions/16522341/pseudo-generics-in-c
  • 哦,确实!所以我必须明白它是可行的吗?
  • 我在谷歌搜索时找不到原始源代码,但我记得读过 Bjarne 在Cfront 编译器(第一个 C++ 编译器)中尝试了类似上述的巨大预处理器宏。如果第一个版本生成了 C 代码,我猜它可能就是模板的制作方式,或者它可能只是与处理它们一起进行的实验。 (它似乎也将模板实例存储在单独的模板存储库中。)

标签: c templates c-preprocessor generic-programming generic-collections


【解决方案1】:

评论者认为这个概念是可行的,因此我会考虑回答这个问题。

欲了解更多信息,您可以查看以下链接:

谢谢。

【讨论】:

    猜你喜欢
    • 2018-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-07
    • 1970-01-01
    相关资源
    最近更新 更多