【问题标题】:Variadic macro expansion for each token每个令牌的可变参数宏扩展
【发布时间】:2020-02-07 00:43:02
【问题描述】:

假设我有一个宏,一个简单的宏,它只为不同类型调用函数foo

#define FOO(type) foo_##type();

假设我想为多种不同类型调用这个东西。具体;

foo_int();
foo_float();
foo_point2d();

我想用一个叫做FOO2的宏来生成上面的代码。

#define FOO2(args...) --fill--here

为了完整起见,FOO2(int, float, point2d) 应该扩展为上面的小代码 sn-p。这是否可以使用宏以及如何为可变参数宏令牌包中的每个参数做不同的、单独的事情?

我确信已经有人问过这样的问题。我搜索了其他几个结果,显示了某种非常复杂和通用的 FOR_EACH 宏实现。这就是为什么我决定询问我的具体用例并提出一个新问题。

【问题讨论】:

  • 您要解决的真正问题是什么?不,不是关于用宏做这种事情的问题,而是你认为解决方案涉及用宏做这种事情的真正问题,所以这就是你要问的。
  • 你可以说,我试图通过使用宏注释为我的结构自动生成 setter 和 getter,我最终需要这样的东西。并不是说这是一个好主意,只是一个实验。但实际上,我所追求的是解决这个孤立案例的方法。
  • 嗯,问题是核心 C++ 中几乎没有什么可以“自动生成”,而您正在与潮流作斗争。在过去有些类似的情况下,我使用了 XML 定义和一些样式表,它们都生成了类声明,以及修改每个类成员的方法。最终的结果是无聊的、普通的 C++。为正确的工作使用正确的工具。
  • BOOST_FUSION_ADAPT_STRUCT等宏的功能,我想这也是可以实现的。
  • 您可能也会感兴趣:stackoverflow.com/q/14137291/298054 - 宏支持空参数,因此如果您不关心一些额外的逗号,您可以拥有一个带有多个参数的宏并传递空参数。

标签: c++ c c-preprocessor


【解决方案1】:

是的,这是可能的,但需要多个宏。

#define MAP1(m,t,...) m(t)
#define MAP2(m,t,...) m(t); MAP1(m,__VA_ARGS__)
#define MAP3(m,t,...) m(t); MAP2(m,__VA_ARGS__)
// ... add more as needed ...
#define MAP(n,...) MAP##n(__VA_ARGS__)

#define FOO(type) foo_##type()
#define FOON(n, ...) MAP(n, FOO, __VA_ARGS__)

FOON(3, int, float, double);

上面会生成:

foo_int(); foo_float(); foo_double();

如果您不想将数字指定为参数,请添加以下内容:

#define FOO1(...) FOON(1, __VA_ARGS__)
#define FOO2(...) FOON(2, __VA_ARGS__)
#define FOO3(...) FOON(3, __VA_ARGS__)
// ... add more as needed ...

现在你可以这样做了:

FOO3(int, float, double);

再做一些工作,您甚至可以使宏与任何函数名一起工作:

#define MAP1(m,f,t,...) m(f,t)
#define MAP2(m,f,t,...) m(f,t); MAP1(m,f,__VA_ARGS__)
#define MAP3(m,f,t,...) m(f,t); MAP2(m,f,__VA_ARGS__)
// ...
#define MAP(n,...) MAP##n(__VA_ARGS__)

#define CALL(funcname, type) funcname##_##type()
#define CALLN(n, funcname, ...) MAP(n, CALL, funcname, __VA_ARGS__)

#define CALL1(...) CALLN(1, __VA_ARGS__)
#define CALL2(...) CALLN(2, __VA_ARGS__)
#define CALL3(...) CALLN(3, __VA_ARGS__)
// ...

CALL1(foo, int);
CALL2(bar, float, double);
CALL3(baz, whatever, you, want);

结果:

foo_int();
bar_float(); bar_double();
baz_whatever(); baz_you(); baz_want();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-29
    • 2019-09-23
    • 2020-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多