V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Entityless
V2EX  ›  C

C/C++ 种通过宏获得函数名的问题

  •  
  •   Entityless · 2020-08-31 14:08:32 +08:00 · 2357 次点击
    这是一个创建于 1550 天前的主题,其中的信息可能已经有所发展或是发生改变。

    实在是不知道怎么用一句标题描述这个问题。。

    场景如下:

    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_doublefunc_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)() {
          |      ^~~~~~~~~~~~~~
    

    请问有什么解决方案吗?

    12 条回复    2020-10-05 21:02:19 +08:00
    InkStone
        1
    InkStone  
       2020-08-31 14:12:21 +08:00
    你的##后面不该带空格的吧。

    另外,只有 C 需要这么写,C++直接重载就好了
    Entityless
        2
    Entityless  
    OP
       2020-08-31 14:20:47 +08:00
    @InkStone 因为平台限制只能支持 C,所以想这么写,,
    BTW,## 后面加不加空格效果都是一样的
    anytk
        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;
    }


    这样?
    Entityless
        4
    Entityless  
    OP
       2020-08-31 14:23:36 +08:00
    // 上文 meta.h 的 META_FUNC_NAME 前面还有个 void
    Entityless
        5
    Entityless  
    OP
       2020-08-31 14:28:02 +08:00
    @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) {
    | ^~~~~~~~~~~~~~
    ```
    anytk
        6
    anytk  
       2020-08-31 14:31:05 +08:00
    @Entityless 提供的里面已经没有用 SUPPLIED_META_TYPE 了,宏就是简单的替换。这里做的就是用宏生成函数声明而已,函数体跟在声明后。
    wty
        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)
    ```

    我之前这么写的(分布在好几个文件里面,摘抄出来的,顺序可能不对),至于为啥要套两遍我也不知道,试出来的,,,,
    pursuer
        8
    pursuer  
       2020-08-31 14:48:08 +08:00
    你写错字了,宏里那个 METY 和参数 META
    C 中有##或#的宏参数好像不会嵌套扩展。可以预先把宏扩展一次,像#7 那样
    Entityless
        9
    Entityless  
    OP
       2020-08-31 14:48:34 +08:00
    @anytk 啊,了解了,谢谢
    不过问题的场景是,对于每种 META_TYPE,函数的执行流程都是一摸一样的(类似于 C++ 的模板函数,,
    Entityless
        10
    Entityless  
    OP
       2020-08-31 14:50:01 +08:00
    @pursuer 哈哈,确实如此,,
    Entityless
        11
    Entityless  
    OP
       2020-08-31 14:55:47 +08:00
    @wty 神了,正解,阿里嘎多!
    codehz
        12
    codehz  
       2020-10-05 21:02:19 +08:00
    话说 c99 的话,是不是可以试试 https://en.cppreference.com/w/c/language/generic
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3400 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 11:44 · PVG 19:44 · LAX 03:44 · JFK 06:44
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.