提问人:danwgh 提问时间:11/27/2022 最后编辑:danwgh 更新时间:11/28/2022 访问量:98
使用 X-Macros 定义匿名枚举会产生编译错误
define anonymous enum with x-macros produces compilation error
问:
我正在做一个大项目,我有很多错误宏。
我想为记录器编写一个辅助函数,将这些 errno 中的每一个字符串化为一个字符串。我决定使用 x-macros,但我收到编译错误
首先,代码是这样的:
// project_errno.h
#define PROJECT_ERR_KEY_FAILURE 12222
#define PROJECT_ERR_CIPHER_ZERO_PADDING 12345
#define PROJECT_ERR_FAILED_TO_SETUP_ENC_KEY 14004
我的整理方式如下:
- 在另一个文件中,我放置了 x-macros:
// project_errno.hx
PROJECT_ERR_FUNC(PROJECT_ERR_KEY_FAILURE) 12222
PROJECT_ERR_FUNC(PROJECT_ERR_CIPHER_ZERO_PADDING) 12345
PROJECT_ERR_FUNC(PROJECT_ERR_FAILED_TO_SETUP_ENC_KEY) 14004
- 然后我把它变成了一个枚举:
// project_errno.h
enum {
#define PROJECT_ERR_FUNC(name, value) name=value,
#include "project_errno.hx"
#undef PROJECT_ERR_FUNC
};
- 然后我添加了一个将由记录器使用的函数:
// logging.h (declaration) and (definition) logging.c
const char* stringify_errno(int errno) {
switch (errno) {
#define PROJECT_ERR_FUNC(name, value) case name: return #value ;
#include "project_errno.hx"
#undef PROJECT_ERR_FUNC
}
}
所以,看起来不错,但我无法让它编译,我得到以下编译错误:
project_errno.h:8:53: error: error: expected identifier before numeric constant
#define PROJECT_ERR_CIPHER_ZERO_PADDING 12345
^
..../project_errno.h:17:30: note: in definition of macro ‘PROJECT_ERR_FUNC’
#define PROJECT_ERR_FUNC(name, value) name=value,
^~~~
..../project_errno.hx:47:14: note: in expansion of macro ‘PROJECT_ERR_CIPHER_ZERO_PADDING ’PROJECT_ERR_FUNC(PROJECT_ERR_CIPHER_ZERO_PADDING, 12345)
project_errno.h:8:53: error: error: expected ‘}’ before numeric constant
#define PROJECT_ERR_CIPHER_ZERO_PADDING 12345
^
..../project_errno.h:17:30: note: in definition of macro ‘PROJECT_ERR_FUNC’
#define PROJECT_ERR_FUNC(name, value) name=value,
^~~~
..../project_errno.hx:47:14: note: in expansion of macro ‘PROJECT_ERR_CIPHER_ZERO_PADDING ’PROJECT_ERR_FUNC(PROJECT_ERR_CIPHER_ZERO_PADDING, 12345)
project_errno.h:8:53: error: expected unqualified-id before numeric constant
#define PROJECT_ERR_CIPHER_ZERO_PADDING 12345
^
..../project_errno.h:17:30: note: in definition of macro ‘PROJECT_ERR_FUNC’
#define PROJECT_ERR_FUNC(name, value) name=value,
^~~~
..../project_errno.hx:47:14: note: in expansion of macro ‘PROJECT_ERR_CIPHER_ZERO_PADDING ’PROJECT_ERR_FUNC(PROJECT_ERR_CIPHER_ZERO_PADDING, 12345)
^~~~~~~~~~~~~~~~~~~~~~~
In file included from ......../project_errno.h:20:1: error: expected declaration before ‘}’ token
};
^
..../project_errno.h:17:30: note: in definition of macro ‘PROJECT_ERR_FUNC’
#define PROJECT_ERR_FUNC(name, value) name=value,
^~~~
..../project_errno.hx:47:14: note: in expansion of macro ‘PROJECT_ERR_CIPHER_ZERO_PADDING ’PROJECT_ERR_FUNC(PROJECT_ERR_CIPHER_ZERO_PADDING, 12345)
^~~~~~~~~~~~~~~~~~~~~~~
我不明白为什么我会收到这些错误(我在同一编译会话中多次收到相同的错误消息),我希望你们能帮助我。 另外,如果您有任何其他解决方案来解决我最初打算解决的问题(使用 errno 宏并添加一个函数来字符串化这些 errno,每当我向项目添加 errno [仅在一个地方]),我很想听听谢谢
答:
0赞
Rulle
11/27/2022
#1
编辑答案:
我能够使用
enum {
#define PROJECT_ERR_FUNC(name) , name =
PROJECT_ERR_START_OF_ENUM = -1
#include "project_errno.hx"
#undef PROJECT_ERR_FUNC
};
但必须删除末尾的反引号。上面的代码只有在你之前没有包含的情况下才有效。project_errno.hx
project_errno.h
一个完整的最低工作计划将是
enum {
#define PROJECT_ERR_FUNC(name) , name =
PROJECT_ERR_START_OF_ENUM = -1
#include "project_errno.hx"
#undef PROJECT_ERR_FUNC
};
#include <iostream>
int main() {
std::cout << PROJECT_ERR_KEY_FAILURE << std::endl;
return 0;
}
这将打印.12222
评论
0赞
danwgh
11/27/2022
首先,它:(没有帮助。我收到相同的错误消息,但有一个额外的换行,在该错误消息的所有混乱中 其次,您需要您建议的解决方案,我们在同一文件中使用它。但在这里,我使用 2 个单独的文件,所以我不需要定义那个 FOREACH,而只需要将“纯文本”放在 project_errno.hx 中并包含它
0赞
Rulle
11/27/2022
@danwgh 为了让它工作,你必须从小处着手:首先复制我的最低工作程序并让它工作。然后从那里继续前进......
0赞
danwgh
11/27/2022
我不明白我怎么能让它工作。正如您所定义的,宏函数甚至不会产生“值”。请注意,我使用的是非连续的数字,所以我不能相信枚举会自己生成这些值。
0赞
Bob__
11/28/2022
#2
我会按照维基百科页面中关于 X 宏的食谱进行操作:
实现
X 宏应用程序由两部分组成:
- 列表元素的定义。
- 扩展列表以生成声明或语句的片段。
该列表由宏或头文件(命名)定义,该文件本身不生成任何代码,而仅由宏(经典命名)的一系列调用和元素的数据组成。每个扩展 的前面都有一个定义 with with 列表元素的语法。对列表中每个元素的 expands 的调用。
LIST
X
LIST
X
LIST
X
特别是第二个示例,即以 X 宏为参数的示例
将工作器宏的名称传递到列表宏中。这既避免了定义名称晦涩的宏 (),又减轻了取消定义它的需要。
X
在 OP 的用例中,这会导致以下三个文件:
// project_errno.h
#ifndef PROJECT_ERRNO_H
#define PROJECT_ERRNO_H
#define FOR_EACH_ERR_ID_VALUE_PAIR(DO) \
DO(PROJECT_ERR_KEY_FAILURE, 12222) \
DO(PROJECT_ERR_CIPHER_ZERO_PADDING, 12345) \
DO(PROJECT_ERR_FAILED_TO_SETUP_ENC_KEY, 14004)
#define DEFINE_ENUM_ITEM(err, value) err = value,
enum project_errs {
FOR_EACH_ERR_ID_VALUE_PAIR( DEFINE_ENUM_ITEM )
};
#undef DEFINE_ENUM_ITEM
#endif
// logging.h
#ifndef LOGGING_H
#define LOGGING_H
const char* stringify_errno(int errno);
#endif
// logging.c
#include <stdio.h>
#include "project_errno.h"
#define STRINGIFY_ERR_VALUE_NAME(name, value) case name: \
return "[" #value "] " #name;
const char* stringify_errno(int errno)
{
switch (errno) {
FOR_EACH_ERR_ID_VALUE_PAIR(STRINGIFY_ERR_VALUE_NAME)
default:
return "[-----] UNKWOWN";
}
}
#undef STRINGIFY_ERR_VALUE_NAME
评论
12222 = , 12222 12345 ...