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

发布于 2024-08-14 09:14:55 字数 1109 浏览 3 评论 0原文

我想做的(出于日志记录的目的)是这样的:

编写此代码是为了显示我的问题,实际代码很复杂,是的,我有充分的理由即使在 C++ 上也使用宏 =)

# define LIB_SOME 1
# define LIB_OTHER 2

# define WHERE "at file #a, line #l, function #f: "
// (look for syntax hightlighting error at SO xd)
# define LOG_ERROR_SIMPLE(ptr, lib, str) ptr->log ("ERROR " str \
                                                   " at library " #lib);
# define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, lib, WHERE str)

LOG_ERROR_SIMPLE (this, LIB_SOME, "doing something")
LOG_ERROR (this, LIB_OTHER, "doing something else")

LOG_ERROR_SIMPLE () 写入 lib 参数的字符串化(由“”括起来的宏名称),

但随后 LOG_ERROR 写入已展开的宏的字符串化(“2”)。这是预期的,因为 lib 在扩展和调用 LOG_ERROR_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_OTHER 并且这个值用于调用LOG_ERROR_SIMPLE,它在该调用之前没有宏扩展)

有某种方法可以在不使用技巧的情况下获得相同的行为吗?

what I'd like to do (for logging purposes) is something like this:

This code has been written to show my problem, actual code is complex and yes, I have good reasons to use macros even on C++ =)

# define LIB_SOME 1
# define LIB_OTHER 2

# define WHERE "at file #a, line #l, function #f: "
// (look for syntax hightlighting error at SO xd)
# define LOG_ERROR_SIMPLE(ptr, lib, str) ptr->log ("ERROR " str \
                                                   " at library " #lib);
# define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, lib, WHERE str)

LOG_ERROR_SIMPLE (this, LIB_SOME, "doing something")
LOG_ERROR (this, LIB_OTHER, "doing something else")

LOG_ERROR_SIMPLE() writes the stringification of the lib parameter (a macro name surrounded by " ")

but then LOG_ERROR writes the stringification of the macro already expanded ("2"). this is expected, since lib got its expansion before expanding and calling LOG_ERROR_SIMPLE. but this is not what I need.

Basically my question is this: how to avoid macro expansion of a macro function parameter when calling another macro function?

There is a trick I use that avoids macro expansion:

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

  LOG_ERROR(this, LIB_OTHER, "some error",)

(pasting x and lib produces LIB_OTHER and this value is used to call LOG_ERROR_SIMPLE, its not macro expanded before that call)

There is some way to obtain this same behaviour without using a trick?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

伤感在游骋 2024-08-21 09:14:55

我正在做:

#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");
}

打印出:

FOO
BAR

Works with MSVC2005 but not with 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);
}

但是,您的纪律是不要使用带有太多参数的宏。 MSVC2005 打印出来

FOO
BAR
FOO2

,而 gcc 打印出来

FOO
BAR
FOOBAR

I'm doing:

#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");
}

which prints out:

FOO
BAR

Works with MSVC2005 but not with gcc/g++.


EDIT: to make it work with gcc/g++ you can abuse variadic macros:

#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);
}

However, it's your discipline not to use the macro with too many parameters. MSVC2005 prints out

FOO
BAR
FOO2

while gcc prints out

FOO
BAR
FOOBAR
彩扇题诗 2024-08-21 09:14:55

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

If you don't need the expanded lib aliases (i.e. '1' & '2') in your cpp macros, you could also use an enum instead of defined values.

我认为你不能。不过,您可以做的是添加一层宏以使其在其位置上剥落:

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

I don't think you can. What you could do, though, is add a layer of macro for it to unpeel in its place:

#define WRAP(x) x
#define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, lib, WHERE WRAP(str))
倾其所爱 2024-08-21 09:14:55

你几乎已经拥有了。 使用

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

在 gcc 上
LOG_ERROR(此,LIB_OTHER,“一些错误”)
产量
this->log ("ERROR " "at file #a, line #l, function #f: " "some error" " at library " "LIB_OTHER");

我也会删除尾随';'从您的宏中,您的代码将如下所示:
LOG_ERROR(this, LIB_OTHER, "一些错误");

You almost had it. Use

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

On gcc
LOG_ERROR(this, LIB_OTHER, "some error")
yields
this->log ("ERROR " "at file #a, line #l, function #f: " "some error" " at library " "LIB_OTHER");

I would also remove the trailing ';' from your macro so that your code would look like:
LOG_ERROR(this, LIB_OTHER, "some error");

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文