用x-宏定义匿名枚举会产生编译错误



我正在做一个大项目,我有很多errno宏。
我想为日志记录器编写一个辅助函数,将这些errno字符串化为字符串。我决定使用x-宏,但我得到编译错误

首先,代码是这样的:

// 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-宏:
// 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
  • 然后我把它变成一个enum:
// 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宏和添加一个函数来字符串化那些errnos每当我添加一个errno到项目[在只有一个地方]),我很乐意听到它谢谢

我会遵循维基百科页面上关于X宏的配方:

实施

X宏应用程序由两部分组成:

  1. 列表元素的定义。
  2. 扩展列表以生成声明或语句的片段。

列表是由宏或头文件(命名为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

可在此测试:https://wandbox.org/permlink/aNJCI7lQihkFnYzp

编辑回答:

我可以使用

生成枚举
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

最新更新