实在是不知道怎么用一句标题描述这个问题。。
场景如下:
meta.h
#define META_FUNC_NAME(META_TYPE) func_## METY_TYPE
META_FUNC_NAME(SUPPLIED_META_TYPE)() {
do_something();
}
#undef SUPPLIED_META_TYPE
test.c:
#define SUPPLIED_META_TYPE float
#include "meta.h"
#define SUPPLIED_META_TYPE double
#include "meta.h"
我希望在 test.c
得到 func_double
和 func_float
两个函数。但是,上面的代码最终会展开出两个 func_METY_TYPE
函数:
In file included from test.c:5:
meta.h:1:35: error: redefinition of ‘func_METY_TYPE’
1 | #define META_FUNC_NAME(META_TYPE) func_## METY_TYPE
| ^~~~~
meta.h:2:6: note: in expansion of macro ‘META_FUNC_NAME’
2 | void META_FUNC_NAME(SUPPLIED_META_TYPE)() {
| ^~~~~~~~~~~~~~
In file included from test.c:2:
meta.h:1:35: note: previous definition of ‘func_METY_TYPE’ was here
1 | #define META_FUNC_NAME(META_TYPE) func_## METY_TYPE
| ^~~~~
meta.h:2:6: note: in expansion of macro ‘META_FUNC_NAME’
2 | void META_FUNC_NAME(SUPPLIED_META_TYPE)() {
| ^~~~~~~~~~~~~~
请问有什么解决方案吗?
1
InkStone 2020-08-31 14:12:21 +08:00
你的##后面不该带空格的吧。
另外,只有 C 需要这么写,C++直接重载就好了 |
2
Entityless OP @InkStone 因为平台限制只能支持 C,所以想这么写,,
BTW,## 后面加不加空格效果都是一样的 |
3
anytk 2020-08-31 14:21:06 +08:00
#define META_FUNC_NAME(meta_type) \
meta_type func_##meta_type(meta_type _arg) META_FUNC_NAME(float) { int x = 1; } META_FUNC_NAME(double) { int y = 1; } 这样? |
4
Entityless OP // 上文 meta.h 的 META_FUNC_NAME 前面还有个 void
|
5
Entityless OP @anytk 好像不行
``` In file included from test.c:5: meta.h:3:45: error: conflicting types for ‘func_SUPPLIED_META_TYPE’ 3 | #define META_FUNC_NAME(meta_type) meta_type func_##meta_type(meta_type _arg) | ^~~~~ meta.h:6:1: note: in expansion of macro ‘META_FUNC_NAME’ 6 | META_FUNC_NAME(SUPPLIED_META_TYPE) { | ^~~~~~~~~~~~~~ In file included from test.c:2: meta.h:3:45: note: previous definition of ‘func_SUPPLIED_META_TYPE’ was here 3 | #define META_FUNC_NAME(meta_type) meta_type func_##meta_type(meta_type _arg) | ^~~~~ meta.h:6:1: note: in expansion of macro ‘META_FUNC_NAME’ 6 | META_FUNC_NAME(SUPPLIED_META_TYPE) { | ^~~~~~~~~~~~~~ ``` |
6
anytk 2020-08-31 14:31:05 +08:00
@Entityless 提供的里面已经没有用 SUPPLIED_META_TYPE 了,宏就是简单的替换。这里做的就是用宏生成函数声明而已,函数体跟在声明后。
|
7
wty 2020-08-31 14:36:21 +08:00 2
```c
#define MergeName1(Name1,Name2) Name1##Name2 #define MergeNames(Name1,Name2) MergeTokens1(Name1,Name2) #define ChannelFunc_Init MergeNames(INST_NAME, _Init) #define INST_NAME Channel0 void ChannelFunc_Init(void) ``` 我之前这么写的(分布在好几个文件里面,摘抄出来的,顺序可能不对),至于为啥要套两遍我也不知道,试出来的,,,, |
8
pursuer 2020-08-31 14:48:08 +08:00
你写错字了,宏里那个 METY 和参数 META
C 中有##或#的宏参数好像不会嵌套扩展。可以预先把宏扩展一次,像#7 那样 |
9
Entityless OP @anytk 啊,了解了,谢谢
不过问题的场景是,对于每种 META_TYPE,函数的执行流程都是一摸一样的(类似于 C++ 的模板函数,, |
10
Entityless OP @pursuer 哈哈,确实如此,,
|
11
Entityless OP @wty 神了,正解,阿里嘎多!
|
12
codehz 2020-10-05 21:02:19 +08:00
话说 c99 的话,是不是可以试试 https://en.cppreference.com/w/c/language/generic
|