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

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

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

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

无论是那个还是做一个foo_int(int,int)和一个foo_char(int, char*)

我认为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)); 

就在这里。 您可以在C11中使用type-generic表达式:

 #include  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*. 

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

 #include  foo(int, ...); 

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

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

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

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

 typedef struct { int type; union { char* char_ptr; int int_val; // etc... }; } foo_data; void foo(foo_data data) { switch (data.type) { case 0: printf("%s\n", data.char_ptr); break; case 1: printf("%i\n", data.int_val); break; } } void main() { foo_data data; data.type = 0; data.char_ptr = "hello"; foo(data); data.type = 1; data.int_val = 12; foo(data); } 

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

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

让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项目中使用它。