C没有模板.我认为你能做的最好的事情就是使用一个联合或者让函数有不同的名字.后一种具有不同名称的方法是这样做的准标准方法(例如fabs fabsf fabsl,OpenGL 也大量使用,也解释了C不能重载函数的事实)
void echo_tpl_s(char const *string) { /* ... */ }
void echo_tpl_i(int number) { /* ... */ }
int main(void) {
echo_tpl_s("Hello world");
echo_tpl_i(42);
}
Run Code Online (Sandbox Code Playgroud)
如果有很多公共代码,您可以决定将其分解为单独的函数
void echo_tpl_s(char const *string) {
prepare_output_device();
printf("%s", string);
unprepare_output_device();
}
void echo_tpl_i(int number) {
prepare_output_device();
printf("%d", number);
unprepare_output_device();
}
Run Code Online (Sandbox Code Playgroud)
或者你可以采用联合方式,它将使函数名相等,而是用meta信息炸掉参数类型.
enum Type {
Number,
String
};
struct Value {
enum Type type;
union {
int number;
char const *string;
} u;
};
void echo_tpl(struct Value value) {
switch(value.type) {
case Number: printf("%d", value.u.number); break;
case String: printf("%s", value.u.string); break;
}
}
int main(void) {
echo_tpl((struct Value) {
.type = String,
.u.string = "Hello world"
});
}
Run Code Online (Sandbox Code Playgroud)
如果你想将值存储在某处然后执行print函数而不关心传递给它的值类型,那么union方式特别适合.在C89中,您需要单独创建值,因为它没有复合文字
int main(void) {
struct Value value;
value.type = String;
value.u.string = "Hello world";
echo_tpl(value);
}
Run Code Online (Sandbox Code Playgroud)
不过,为这个创建函数是个好主意
struct Value stringval(char const *string) {
struct Value value;
value.type = String;
value.u.string = string;
return value;
}
struct Value numberval(int number) {
struct Value value;
value.type = Number;
value.u.number = number;
return value;
}
int main(void) {
echo_tpl(stringval("Hello world!"));
}
Run Code Online (Sandbox Code Playgroud)
一些编译器可能会提供编写此类内容的扩展.例如Clang在C中提供函数重载.
void echo_tpl(int value) __attribute__((overloadable)) {
printf("%d", value);
}
void echo_tpl(char const *value) __attribute__((overloadable)) {
printf("%s", value);
}
Run Code Online (Sandbox Code Playgroud)
这解决了函数的调用方不依赖于类型.在定义方面,您仍然需要编写两次代码.这主要是因为(另一个答案解释)C没有类型通用输出函数.当然,如果您使用此功能,您的代码将变为不可移植.