fb5*_*b55 31 c generics c-preprocessor
我需要实现一些使用不同数字数组的方法.通常,我会使用泛型来完成这项工作,但由于C不提供它们,我现在正试图使用宏来模拟它们.
这是我正在尝试做的一个例子:
#ifndef TYPE
#define TYPE int
#endif
TYPE get_minimum_##TYPE (TYPE * nums, int len){
TYPE min = nums[0];
for (int i = 1; i < len; i++) {
if (nums[i] < min) {
min = nums[i];
}
}
return min;
}
Run Code Online (Sandbox Code Playgroud)
但是,这不会编译.clang错误消息:
错误:预期';' 在顶级声明者之后
有没有办法在C中这样做?或者我需要手动为每种类型实现这个吗?
Pau*_*l R 36
您可以在头文件中执行以下操作:
//
// generic.h
//
#define TOKENPASTE(x, y) x ## y
#define GET_MINIMUM(T) TOKENPASTE(get_minimum_, T)
TYPE GET_MINIMUM (TYPE) (TYPE * nums, size_t len){
TYPE min = nums[0];
for (size_t i = 1; i < len; i++) {
if (nums[i] < min) {
min = nums[i];
}
}
return min;
}
Run Code Online (Sandbox Code Playgroud)
然后#include它在每个所需类型的源文件中,例如:
//
// generic.c
//
#define TYPE int
#include "generic.h"
#undef TYPE
#define TYPE float
#include "generic.h"
#undef TYPE
Run Code Online (Sandbox Code Playgroud)
您可以通过预处理器运行它来测试它:
$ gcc -E generic.c
int get_minimum_int (int * nums, size_t len){
int min = nums[0];
for (size_t i = 1; i < len; i++) {
if (nums[i] < min) {
min = nums[i];
}
}
return min;
}
float get_minimum_float (float * nums, size_t len){
float min = nums[0];
for (size_t i = 1; i < len; i++) {
if (nums[i] < min) {
min = nums[i];
}
}
return min;
}
Run Code Online (Sandbox Code Playgroud)
Jeh*_*han 31
实际上,您可以做的最好的事情是定义一个宏,它将为给定的类型生成函数.
#define define_get_minimum(T) \
T get_minimum_##T(T* nums, int len){ \
T min = nums[0]; \
for (int i = 1; i < len; i++) { \
if (nums[i] < min) { \
min = nums[i]; \
} \
} \
return min; \
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以调用该宏来定义所需的特化(使用C++模板,类似的事情由编译器自动完成).
define_get_minimum(int)
define_get_minimum(double)
define_get_minimum(float)
Run Code Online (Sandbox Code Playgroud)
C++编译器自动执行的另一件事是推导出您需要的重载函数.你不能在C中拥有它,所以你必须告诉你正在使用它的专业化.您可以使用以下宏来模拟函数的类似模板的语法(C++ <>只是替换为()):
#define get_minimum(T) get_minimum_##T
Run Code Online (Sandbox Code Playgroud)
然后,您应该能够通过以下方式调用它:
int main()
{
// Define arr as char* array...
// Do stuff...
int res = get_minimum(int)(arr, 3);
}
Run Code Online (Sandbox Code Playgroud)
我没有测试这段代码,但它应该可以工作.