当前位置: 首页 > 知识库问答 >
问题:

在C++预处理器宏中展开__va_args__的var名称

闾丘诚
2023-03-14

我正在尝试实现一个正确的枚举到字符串宏,它将自动实现枚举值和代码中的名称之间的关联。

例如,我想定义一个名为“test”的新宏,如下所示:

ENUM_STR_DECLARE(Test, 1, test1, test2, test3)

这样,通过调用TestEnumToString(test2),我可以访问字符串“test2”。目前,这个enum_str_declare的当前实现如下所示:

#define ENUM_STR_DECLARE(enumName, intOffset, v1, ...)\
  enum enumName { v1 =  intOffset, __VA_ARGS__};\
  const char *enumName##EnumStringArray[] = { #v1 ,#__VA_ARGS__};\
  const char *enumName##EnumToString(value) { return enumName##EnumStringArray[ value - offset ]; }

虽然当我这样做时,__va_args__处理的枚举没有得到正确的名称分隔:

enum Test {
    test1 = 1, test2, test3
};
const char *TestEnumStringArray[] = {"test1", "test2, test3"};
const char *TestEnumToString(value) { return TestEnumStringArray[ value - offset]; }

因为我希望使用“test2”,“test3”而不是“test2,test3”

有没有办法用逗号分隔来展开#__va_args__名称?

干杯!

共有1个答案

史超英
2023-03-14

使用boost预处理器:

#include <boost/preprocessor/tuple.hpp>
#include <boost/preprocessor/seq.hpp>
#include <boost/preprocessor/stringize.hpp>

#define MACRO_DELIM(r, data, elem) BOOST_PP_STRINGIZE(elem) ,

#define DELIMITED_STRINGIZE(...) \
    BOOST_PP_SEQ_FOR_EACH(MACRO_DELIM, _, \
        BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__)))
    
#define ENUM_STR_DECLARE(enumName, intOffset, v1, ...)\
  enum enumName { v1 =  intOffset, __VA_ARGS__};\
  const char *enumName##EnumStringArray[] = { DELIMITED_STRINGIZE(v1, __VA_ARGS__)};\
  const char *enumName##EnumToString(value) { return enumName##EnumStringArray[ value - offset ]; }

ENUM_STR_DECLARE(Test, 1, test1, test2, test3)

演示:

http://coliru.stacked-crooked.com/A/3F3376F2D4ABE266

 类似资料:
  • 当我在一个大型项目中工作时,我偶然发现了一个错误,在这个错误中,一个宏没有正确地扩展。结果输出是“”,但被定义为“”,因此很明显输出应该是“”。 “没问题”,我心想。“这可能是一些愚蠢的错误,毕竟这里有一些讨厌的宏,有很多地方会出错”。正如我所想的那样,我将行为不端的宏隔离到它们自己的项目中,大约200行,并开始在MWE上工作以确定问题所在。200行变成了150,又变成了100,然后是20,10…

  • 预处理器是一些指令,指示编译器在实际编译之前所需完成的预处理。 所有的预处理器指令都是以井号(#)开头,只有空格字符可以出现在预处理指令之前。预处理指令不是 C++ 语句,所以它们不会以分号(;)结尾。 我们已经看到,之前所有的实例中都有 #include 指令。这个宏用于把头文件包含到源文件中。 C++ 还支持很多预处理指令,比如 #include、#define、#if、#else、#line

  • #include <stdio.h> #define NAME "Joe" int main() { printf ("Hello %s\n", NAME); return 0; } 技巧 使用gcc -g编译生成的程序,是不包含预处理器宏信息的: (gdb) p NAME No symbol "NAME" in current context. 如果想在gdb中查看宏信息,可以使

  • 主要内容:1. 预处理器示例,2. 预定义的宏,3. 预处理器运算符,4. 参数化宏Objective-C预处理器不是编译器的一部分,而是编译过程中的一个单独步骤。 简单来说,Objective-C预处理器只是一个文本替换工具,它指示编译器在实际编译之前进行必要的预处理。 我们将Objective-C预处理器称为OCPP。 所有预处理器命令都以井号()开头。它必须是第一个字符(前面不能有空格),并且为了便于阅读,预处理器指令应该从第一列开始。 以下部分列出了所有重要的预处理程序指

  • 在我的代码中,我使用了预处理器宏 但后来我意识到我需要一个内联函数,并最终得到了以下代码 它有效吗?这似乎有效,但不会造成任何潜在问题吗?

  • 主要内容:C# 中的预处理器指令,#define 预处理器,条件指令预处理指令的作用主要是向编译器发出指令,以便在程序编译开始之前对信息进行一些预处理操作。在 C# 中,预处理器指令均以 开头,并且预处理器指令之前只能出现空格不能出现任何代码。另外,预处理器指令不是语句,因此它们不需要以分号 结尾。 在 C# 中,预处理指令用于帮助条件编译。不同于 C 和 C++ 中的指令,在 C# 中不能使用这些指令来创建宏,而且预处理器指令必须是一行中唯一的代码,不能掺杂其它