C中是否有C语言模板的等价物?

时间:2010-05-20 12:54:54

标签: c

在我写的代码中,我需要foo(int, char*)foo(int, int)个函数。

如果我用C ++编写代码,我会使用模板。 C有什么等价物吗?或者我应该使用void指针?怎么样?

7 个答案:

答案 0 :(得分:28)

我认为C中最接近模板的是一些丑陋的宏代码。例如,要定义一个返回其参数两倍的简单函数:

#define MAKE_DOUBLER(T)  \
    T doubler_##T(T x) { \
        return 2 * x;    \
    }

MAKE_DOUBLER(int)
MAKE_DOUBLER(float)

请注意,由于C没有函数重载,你必须使用函数的名称来玩弄(上面同时生成doubler_intdoubler_float,你必须调用它们那样)。

printf("%d\n", doubler_int(5));
printf("%f\n", doubler_float(12.3));

答案 1 :(得分:14)

你做不到。
在C中没有重载,一个函数,一个名称,您需要使用支持您所有需求的类型,例如(void *)

要么是foo_int(int,int)还是foo_char(int, char*)

答案 2 :(得分:11)

是的,有。您可以在C11中使用type-generic表达式:

#include <stdio.h>

void foo_char_ptr(int a, char *b) {
  printf("Called int, char*.\n");
}

void foo_int(int a, int b) {
  printf("Called int, int.\n");
}

#define foo(a, b) _Generic((b), char*: foo_char_ptr, int: foo_int)(a, b)

int main() {
  foo(1, 1);
  foo(1, "foo");
}

// Output:
// Called int, int.
// Called int, char*.

答案 3 :(得分:6)

其他人已经讨论了c在超载方面的内在局限性。但请注意,如果您可以推断出需要哪种情况,您可以使用varargs:

#include <stdarg.h>
foo(int, ...);

如果你无法推断它,你可以传递一个额外的论点:

foo(int, char *spec, ...);

其中spec告诉函数在后续参数中期望什么。与printfscanf系列函数一样。实际上,您可能会发现重复使用printf / scanf约定来指定类型很方便,从而使用户不必使用另一种迷你语言。

答案 4 :(得分:3)

而不是void *您也可以使用联合来保存您需要的任何类型的数据:

LApply.ApplyUpdates('table_name', 'query.Command');

当然,您应该为类型值创建常量。

答案 5 :(得分:2)

可以使用模板标题实现模板。

让foo.h像这样:

#ifndef PREFIX
    #define PREFIX
#endif
#define CCAT2(x, y) x ## y
#define CCAT(x, y) CCAT2(x, y)
#define FN(x) CCAT(PREFIX, x)

#ifndef T
    #error Template argument missing.
#endif

void FN(foo)(int x, T t)
{
    // Whatever.
}


#undef T
#undef PREFIX
#undef CCAT2
#undef CCAT
#undef FN

要使用它,您可以:

#define T char*
#define PREFIX pchar_
#include "foo.h"

#define T int
#define PREFIX int_
#include "foo.h"

现在您可以使用pchar_foo()int_foo()

这样做的好处是,如果存在构建问题,则在模板头中获取行号而不是编译器只是说宏是错误的,并且代码完成在某些IDE中也有效。

PREFIXCCATFN宏非常常见,因此我将其定义提取到一个单独的标题中,并将其定义为另一个标题。

我使用这种模式实现了部分STL以获得乐趣,并在我的一些C项目中使用它。

答案 6 :(得分:-1)

您可以使用GCC中的_Generic。 (尽管这不能移植到其他编译器中) http://www.robertgamble.net/2012/01/c11-generic-selections.html