【问题标题】:Macro definition causing error during composition宏定义导致合成时出错
【发布时间】:2021-06-04 15:27:35
【问题描述】:

我正在尝试让宏打印出文件名,然后是行号,然后是打印消息,这是我正常执行此操作的方法,它可以工作,但它会打印出文件的整个文件路径:

#define TESTER1(...) printf(ANSI_COLOR_BOLD_GREEN "LOG::" __FILE__ ":" STR(__LINE__) "\t" ANSI_COLOR_RESET ANSI_COLOR_GREEN __VA_ARGS__); printf(ANSI_COLOR_RESET "\n")

这可行,但文件路径太长: 示例输出:

C:\Users\Work\Documents\CastEngine\CastDriver\src\main.cpp:18: Example

我想要的输出如下:

main.cpp:18: Example

所以这里是宏:

#define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
#define TESTER2(...) printf(ANSI_COLOR_BOLD_GREEN "LOG::" __FILENAME__ ":" STR(__LINE__) "\t" ANSI_COLOR_RESET ANSI_COLOR_GREEN __VA_ARGS__); printf(ANSI_COLOR_RESET "\n")

我知道__FILENAME__ 按预期工作,因为没有定义 TESTER2,我使用以下代码:

printf("%s:%d", __FILENAME__, __LINE__);

输出正是我想要的:main.cpp:19

但是当我从上面添加 TESTER2 定义时,它给了我以下错误:

error: expression cannot be used as a function
 #define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
                                                                                       ^
C:\Users\Work\Documents\CastEngine\CastDriver\src\main.cpp:11:59: note: in expansion of macro '__FILENAME__'
 #define TESTER2(...) printf(ANSI_COLOR_BOLD_GREEN "LOG::" __FILENAME__ ":" STR(__LINE__) "\t" ANSI_COLOR_RESET ANSI_COLOR_GREEN __VA_ARGS__); printf(ANSI_COLOR_RESET "\n")
                                                           ^~~~~~~~~~~~
C:\Users\Work\Documents\CastEngine\CastDriver\src\main.cpp:20:5: note: in expansion of macro 'TESTER2'
     TESTER2("Hello\n");

我真的不知道如何解决这个问题;任何帮助将不胜感激。

【问题讨论】:

  • 字符串连接仅适用于字符串文字(__FILE__ 扩展为文字),不能用表达式连接字符串。
  • 您不能使用双下划线创建名称。这些名称是为您的实现保留的。
  • @Barmar,有没有办法在保持单行宏的同时将其输出转换为文字?
  • 当然不是。字面量在编译时存在,函数在运行时调用。
  • @Barmar 那么有没有办法做到这一点?

标签: c++ c macros


【解决方案1】:

您可以有多个连续的string literals,编译器会将它们视为一个。

例子:

printf("He" "llo" "wo" "rld.");

但在您的宏中 __FILENAME__ 扩展为 strrchr 调用 + 三元运算,其结果不是 string literal - 因此语法错误。

#define TESTER2(...) printf(ANSI_COLOR_BOLD_GREEN "LOG::%s" ":" STR(__LINE__) "\t" ANSI_COLOR_RESET ANSI_COLOR_GREEN __VA_ARGS__, __FILENAME__); printf(ANSI_COLOR_RESET "\n")

【讨论】:

    【解决方案2】:

    你总是可以只使用一个函数来清理它。

    printf("%s:%d",
           absl::StripPrefix(__FILENAME__, "C:\Users\Work\Documents\CastEngine\CastDriver\"),
           __LINE__);
    

    【讨论】:

    • 这缺少 TESTER2() 宏尝试打印的所有其他内容。
    • @Barmar:添加所有其他内容似乎相对微不足道?
    • 你这么认为?展示如何去做。请记住,它是一个可变参数宏,它正在扩展为对printf()的另一个调用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-05
    • 2017-10-19
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多