C ++停止预处理器宏扩展

luf*_*747 5 c++ preprocessor c++11 preprocessor-directive

这是我的示例代码https://godbolt.org/z/VKgKik

#define delete MyCustomDelete(__FILE__, __LINE__), delete

#define CAT(X,Y) CAT2(X,Y)
#define CAT2(X,Y) X##Y
#define CAT_3(X,Y,Z) CAT(X,CAT(Y,Z))    


class A {
    A() = CAT_3(de,le,te);
};
Run Code Online (Sandbox Code Playgroud)

设置Godbolt示例以显示预处理器输出。目的是在预处理阶段结束时,我希望输出代码为

class A {
    A() = delete;
};
Run Code Online (Sandbox Code Playgroud)

当前显示的是“ ThisShouldNotshowUp”。我以为使用##运算符会阻止预处理器重新扩展,但并没有。

我意识到删除“ #define delete”将解决问题,但我需要在此进行定义。我创建一个与删除名称相同的宏的原因是,我希望能够跟踪新闻和删除,并且如果发生内存泄漏,我可以看到分配给它的代码行。因此,该宏意味着我可以继续在代码中使用关键字delete,并免费填写文件和行号。据我所知,除定义删除宏外,没有其他方法可以实现此功能。这是问题的症结所在。delete宏给了我一个强大的调试工具,但是它删除了一个有用的语言功能供我使用。

Mic*_*her 6

您没有机会通过扩展宏来创建预处理令牌,该令牌是类似对象的宏的名称。n3337的相关部分是[cpp.rescan]。我在其中引用了第一段的缩短部分。

在替换列表中的所有参数都被替换并#进行##处理之后,daccess-ods.un.org daccess-ods.un.org 然后,对生成的预处理令牌序列进行重新扫描,以查找更多要替换的宏名称。

尽管存在该问题,但从delete技术上讲它是禁止使用的宏名称,但无法阻止重新扫描时识别该宏名称。

你可能混淆了一个事实,##符不使用它的参数没有的想法,扩张的结果##不进行宏扩展。


Rei*_*ica 3

你想要做的事情是不可能的,正如Michael Karcher 的回答所述:#define delete已经使程序格式错误,并且无法避免扩展类似对象的宏(在其自身的扩展之外)。

但是,对于问题中详细说明的特定用例,可以使用解决方法。您可以将您的内容#define delete放入头文件中(我们称之为头文件debug_delete.hxx),如下所示:

#ifdef delete
# undef delete
#endif
#define delete MyCustomDelete(__FILE__, __LINE__), delete
Run Code Online (Sandbox Code Playgroud)

然后,创建另一个头文件(我们称之为normal_delete.hxx):

#ifdef delete
# undef delete
#endif
Run Code Online (Sandbox Code Playgroud)

请特别注意,这些标头中没有机制来防止多重包含;事实上,我们希望它们可以包含任意次数。

然后,包装必须= delete;在适当的#include指令中使用的代码:

class A {
#include "normal_delete.hxx"
    A() = delete;
#include "debug_delete.hxx"
    ~A() { delete p; }
};
Run Code Online (Sandbox Code Playgroud)

(是的,它很丑陋,但是您所做的事情首先有点丑陋,因此可能需要丑陋的代码才能使其工作)。