同名的类函数宏和枚举器

Posted

技术标签:

【中文标题】同名的类函数宏和枚举器【英文标题】:Function-like macro and enumerator with the same name 【发布时间】:2019-03-14 09:26:16 【问题描述】:

在下面的片段中,我有一个 struct IndexError 当用户使用我的库出错时返回。我有一个类似函数的宏,它将一个指向IndexError* 的指针和一个枚举都称为INDEX_ERROR

enum errors 
    SUCCESS,
    INVALID_ARGUMENT,
    INDEX_ERROR
;

struct Error 
    char error_buff[BUFSIZ];
;

typedef struct Error Error;

struct IndexError 
    Error  parent;
    size_t invalid_index;
    // etc.
;

typedef struct IndexError IndexError;


#define INDEX_ERROR(obj) ((IndexError*) obj)

我将如何使用它的一个例子是:

size_t pos = 4;
int IndexPointer* error = NULL;
int status = array_remove_item(my_array, pos, &error);

然后我检查状态。如果它没有返回SUCCESS,我会检查错误,因为那应该指向一个新创建的错误。

其中一个数组函数的实现可能如下所示:

int array_remove_item(Array* array, size_t pos, Error** error_out)

    Error* error = NULL;
    if(pos >= array->size) 
        index_error_create(INDEX_ERROR(&error), pos); // use casting macro.
        *error_out = error;
        return INDEX_ERROR; // is this the macro or the value from the errors enum?
    
    priv_array_remove_item(array, pos);
    return SUCCESS;

所以我的问题是,在return INDEX_ERROR;INDEX_ERROR 会从枚举中返回值,还是预处理器会因为我的命名不方便而咬我?

【问题讨论】:

宏替换发生在一个单独的阶段之前其他标识符通过编译器。 This translation phase reference 可能会有所帮助。 宏在编译之前得到扩展。因此,您的枚举值 INDEX_ERROR 将被宏文本替换。但是,我希望预处理器会抱怨您在没有参数的情况下引用了宏。 不直接相关,但_This _Sort 的标识符保留给实现以供任何使用。你可以声明typedef struct Error Error;就好了。 另请注意,在 C(以及 C++,但将来只标记您实际编程的语言,因为 C 和 C++ 是两种非常不同的语言)中以下划线开头的符号和后跟一个大写字母(例如_Error)在编译器和标准库的所有范围内保留。您通常不应自己定义此类符号。 @StoryTeller 编辑并删除了下划线 【参考方案1】:
return INDEX_ERROR; // is this the macro or the value from the errors enum?

它是枚举器。它不可能是扩展类函数宏的结果,因为它没有紧跟左括号( 标记,因为预处理器需要1

虽然有点臭。宏和枚举器的不同名称将使代码更清晰和不言自明,无需阅读语言规范的细则。


1 - n1570 6.10.3p10 "Each subsequent instance of the function-like macro name followed by a ( as the next preprocessing token introduces the sequence of preprocessing tokens that is replaced by the replacement list in the definition"

【讨论】:

那个链接不能让我的浏览器满意,因为连接不安全。 @hetepeperfan - 真的吗?我使用的是最新的 chrome,它可以很好地打开链接(而且 chrome 因其对 https 链接的严格性而臭名昭著)。 我用的是Ubuntu16.04自带的Firefox,可能有点老了。 Anway,这是我使用的标准草案的标识符(编辑到问题中),以及章节号。您可以从其他来源进行验证。

以上是关于同名的类函数宏和枚举器的主要内容,如果未能解决你的问题,请参考以下文章

来自不同命名空间的同名对象的可重用函数代码?

Qt的元系统真的那么乏味吗?

是否可以在同一个字符序列上有一个类似函数的宏和一个类似对象的宏?

用来枚举属性的对象工具函数

EXCEL宏和函数与组合框

宏和函数的区别