【发布时间】:2019-04-19 11:16:00
【问题描述】:
我正在尝试在 C 中做一些模板的东西: 我需要创建一个带有函数的二维向量结构来处理它们,并且我需要将它们用于 int、unsigned int、float、double 甚至其他类型都支持基本数学功能的类型。
我可以为每种类型编写所有代码。如果我在其中一个中编写错误,我可能会忘记修复所有其他错误。我之前在 C++ 中做过,我只是使用模板,但现在我想要在 C (C11) 中......没有。
所以我查看了宏,我发现可以使用## 标签来逐字使用宏的传递参数。
这是我尝试过的一些代码:
#define DECLARE_VEC2(N, T) \
typedef struct { T x, y;} N; \
inline N *##N_new() { return malloc(sizeof(N));}
DECLARE_VEC2(vec2i, int);
DECLARE_VEC2(vec2f, float);
DECLARE_VEC2(vec2d, double);
它不起作用。 ##N 不会被 vec2i/vec2f/vec2d 替换,而只是保持 ##N 甚至只是 N。编译器不会接受它,当我在文件上使用 -E 标志运行 gcc 时,我看到预处理器确实不能代替它。
但是,如果我在 ##N 和 _new 之间添加一个空格,预处理器会替换它,但空格也在那里,这显然会在编译时出现问题。
但是,如果我将函数名称更改为 new_##N,它不仅可以很好地进行预处理,而且可以完美地工作。
但我不想要后者! 我以这种方式创建了所有具有功能的结构:typename_function() 并且不想因为这个愚蠢的问题而改变它。
那么,问题是:有没有办法解决这个问题?
注意:我也尝试过向包含下划线的宏添加一个额外的参数,甚至在添加下划线的宏中声明一个宏,但它们都遇到了同样的问题:需要某种分隔符这使预处理器理解名称在下划线之前或后面的任何内容之前结束。
编辑:奇怪的是,当使用 ##N##_new() 之类的东西时,预处理器会很好地替换名称,但随后不会接受它并出现以下错误:
error: pasting "*" and "vec2i" does not give a valid preprocessing token
inline N * ##N##_new() { return malloc(sizeof(N));}
虽然生成的代码似乎是正确的(gcc -E):
typedef struct { int x, y;} vec2i; inline vec2i *vec2i_new() { return malloc(sizeof(vec2i));};
【问题讨论】:
-
inline N * N##_new(void)