C++ CPP:避免宏函数参数的宏扩展

C++ CPP:避免宏函数参数的宏扩展,c++,c,macros,c-preprocessor,stringification,C++,C,Macros,C Preprocessor,Stringification,我想做的事情(出于日志目的)如下: 此代码已被写入以显示我的问题,实际代码复杂,是的,我有充分的理由使用宏即使在C++= LOG\u ERROR\u SIMPLE() 但是LOG\u ERROR写入已扩展宏的字符串化(“2”)。这是意料之中的,因为lib在扩展和调用LOG\u ERROR\u SIMPLE之前进行了扩展。但这不是我需要的 基本上我的问题是:调用另一个宏函数时,如何避免宏函数参数的宏扩展 我使用了一个技巧来避免宏扩展: LOG_ERROR(ptr, lib, str, x) L

我想做的事情(出于日志目的)如下:

此代码已被写入以显示我的问题,实际代码复杂,是的,我有充分的理由使用宏即使在C++=

LOG\u ERROR\u SIMPLE()

但是
LOG\u ERROR
写入已扩展宏的字符串化(“2”)。这是意料之中的,因为lib在扩展和调用
LOG\u ERROR\u SIMPLE
之前进行了扩展。但这不是我需要的

基本上我的问题是:调用另一个宏函数时,如何避免宏函数参数的宏扩展

我使用了一个技巧来避免宏扩展:

  LOG_ERROR(ptr, lib, str, x) LOG_ERROR_SIMPLE(ptr, x##lib, WHERE str)

  LOG_ERROR(this, LIB_OTHER, "some error",)
(粘贴x和lib会产生
lib\u OTHER
,此值用于调用
LOG\u ERROR\u SIMPLE
,在调用之前不会展开宏)


有什么方法可以不使用技巧就获得同样的行为?

我认为你做不到。不过,您可以做的是为其添加一层宏,以便在其位置取消显示:

#define WRAP(x) x
#define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, lib, WHERE WRAP(str))
我正在做:

#include <cstdio>

#define FOO 1
#define BAR 2

#define LOG_SIMPLE(ptr, lib, str) printf("%s\n", #lib);
#define LOG(ptr, lib, str) LOG_SIMPLE(ptr, ##lib, str)

int main()
{
  LOG_SIMPLE(0, FOO, "some error");
  LOG(0, BAR, "some other error");
}
适用于MSVC2005,但不适用于gcc/g++


编辑:要使其与gcc/g++一起工作,您可以滥用可变宏:

#include <stdio.h>

#define FOO 1
#define BAR 2

#define LOG_SIMPLE(ptr, str, lib) printf("%s\n", #lib);
#define LOG(ptr, str, lib, ...) LOG_SIMPLE(ptr, str, lib##__VA_ARGS__)

int main()
{
  LOG_SIMPLE(0, "some error", FOO);
  LOG(0, "some other error", BAR);
  LOG(0, "some other error", FOO, BAR);
}
当gcc打印出来时

FOO
BAR
FOO2
FOO
BAR
FOOBAR
你差点就成功了。使用

#define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, ##lib, WHERE str)
关于gcc
LOG\u错误(这个,LIB\u其他,“一些错误”)

收益率
this->log(“错误”位于文件a的第1行,函数f:“某些错误”位于库“LIB#u OTHER”)

我还将删除尾随的“;”使您的代码看起来像:

LOG_错误(这个,LIB_其他,“一些错误”)

如果在cpp宏中不需要扩展库别名(即“1”和“2”),也可以使用枚举而不是定义的值。

当使用GCC的预处理器(删除不存在的
#include
)时,我在stdout上得到正确的程序,但在stderr上得到错误消息。t、 c:11:1:错误:粘贴“,”和“条”没有给出有效的预处理标记。好吧,“不工作”有点强。当我运行
gcc-et.c
时,我确实在标准输出上得到了一个可编译的程序。是的,粘贴是一种不适当地扩展“库中的内容”并使其到达日志的方法。我前面的示例使用空参数粘贴lib,您的示例使用左逗号粘贴lib(当然不是完全“右”)。我想知道我是否可以用“一个特殊的隐藏参数”来粘贴lib,以获得与在宏中使用额外参数相同的结果,并为此目的将其保留为空。是的,这是一个很好的技巧!不幸的是,我已经在LOG和LOG_SIMPLE上使用了可变宏。。为了简单起见,我没有指定它,这是我的错。这就是为什么我不指望VA_ARGS以更优雅的方式作为不粘贴任何内容的来源。我今天尝试了更多,但运气不好,我们是否决定在一般情况下不能避免扩展?我认为OP希望避免引用该论点,因此提出了问题。如果“LIB_OTHER”对他没问题,我想他一开始就不会问,用逗号粘贴LIB会出现这样的错误:粘贴“,”和“LIB_OTHER”不会给出有效的预处理标记。是否有一些“中性”字符或隐藏的空参数,我可以用来粘贴库与“某物空”,没有错误?对不起。我误解了你的需要。BOOST_PP_EMPTY是一个扩展为零的宏。您也可以尝试/**/(这是一个空的c风格注释,以防markdown终止它)您是否可以提供所需的宏输出?给定LOG_ERROR(这个,LIB_OTHER,“一些错误”)你想要生成什么代码?@kts,更多的是宏本身,它的工作方式和宏扩展的东西,而不是C代码生成。我只想将LIB_OTHER字符串化以获得“LIB_OTHER”".. 当然,LIB_OTHER必须作为一个参数传递,并且在两级宏函数调用后仍然有效,这不是一件小事。@kts-Ooh,你知道什么。我想到了一件事,Boost的boffins比我领先了一大步。包裹和身份都不起作用。。因为(至少在CPP中)它使用WRAP()作为参数调用LOG_ERROR_SIMPLE,而不是作为“名称内部的内容,但随后未展开”Erk。在这种情况下,我认为您要么在用户上输入LOG_ERROR(ptr、lib、WRAP(str)),要么在不引用LOG_ERROR_SIMPLE的情况下写出LOG_ERROR。虽然我希望找到宏扩展问题的解决方案,但您让我重新思考了其中的一个要素。我已经将我的宏常量更改为枚举,它们的名称没有得到宏扩展(因为它们不是宏),现在问题没有解决,但它消失了=)现在我仍然想解决它,但就我的程序而言,由于您的建议,我不需要。。
FOO
BAR
FOOBAR
#define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, ##lib, WHERE str)