【问题标题】:Iterating Variadic Macro Arguments迭代可变参数宏参数
【发布时间】:2011-05-31 21:55:49
【问题描述】:

我正在以编程方式生成一堆仿函数,为了使生成的代码更具可读性,我正在尝试提出一个宏来扩展以下行,

SET_STATE(FunctorA,a,b);

ref a;
ref b;
FunctorA(ref a, ref b){
   this->a = a;
   this->b = b;
}

基本上它将扩展到第一个参数构造函数。可变参数部分是构造函数的参数数量。是否可以在宏内部循环并在预处理期间生成此代码,即使它对这种特殊情况没有意义,但我有一些具有 20 个左右变量的仿函数,它们可以访问它会清理我生成的代码很多。

所有参数的类型相同,只有名称不同。

【问题讨论】:

  • 我不知道你的问题的答案,但你有没有考虑过类似class FunctorA { public: struct FunctorAParams{ ref A; ref B; ... }; FunctorA(const FunctorAParams &params) : params(params) {} private: const FunctorAParams params; };的问题。
  • Boost.Preprocessor,但我无法输入这个 OTOH。 :)
  • 是"ref a; ref b;关于宏输出的子程序声明部分吗?
  • 是的,它们属于函子。
  • 是否有特定的平台可以使用?

标签: c++ c c-preprocessor


【解决方案1】:

如果允许boost::preprocessorSEQ 表示((a)(b)...), 可能以下代码将达到目的:

#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>

#define DEF_MEMBER( r, data, elem ) ref elem;
#define DEF_PARAM( r, data, i, elem ) BOOST_PP_COMMA_IF( i ) ref elem
#define DEF_ASSIGN( r, data, elem ) this->elem = elem;

#define SET_STATE( f, members )                         \
  BOOST_PP_SEQ_FOR_EACH( DEF_MEMBER,, members )         \
  f( BOOST_PP_SEQ_FOR_EACH_I( DEF_PARAM,, members ) ) { \
      BOOST_PP_SEQ_FOR_EACH( DEF_ASSIGN,, members )     \
  }

SET_STATE(FunctorA,(a)(b))

以上代码扩展为

ref a; ref b; FunctorA( ref a , ref b ) { this->a = a; this->b = b; }

在我的环境中。

【讨论】:

  • @Xeo:谢谢! :-) 可能对于 OP 来说,对 boost 的依赖可能很重......
  • Boost 可能非常松散耦合。例如,我怀疑 Boost.Preprocessor 库依赖很多,所以如果需要,肯定可以提取所需的文件。
  • @MatthieuM.:感谢您的指出。正如您所提到的,Boost.Preprocessor 似乎具有很高的模块化。可能只提取boost/preprocessor 目录就足以立即使用它。
  • Boost.Preprocessor 旨在与纯 C 编译器以及 C++ 编译器一起使用。我相信它是 boost 中唯一的 C 库。
  • 我成功适配了这段代码,只包含了Boost的预处理库。
【解决方案2】:

使用在此链接http://cplusplus.co.il/2010/07/17/variadic-macro-to-count-number-of-arguments/ 中找到的技巧来计算参数的数量并使用一些非常丑陋的宏,我可以生成您想要的输出。

我使用 gcc (gcc -E test.cpp) 对其进行了测试,它可以工作,它不是便携式的

代码:

#define VA_NARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N
#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define SET_STATEGENERATE(name, count, ...)             \
        dec ## count (__VA_ARGS__)                      \
        name(ref ## count (__VA_ARGS__)) {              \
            con ## count (__VA_ARGS__)                  \
        }
#define SET_STATEP(name, count, ...) SET_STATEGENERATE(name, count, __VA_ARGS__) 
#define SET_STATE(name, ...) SET_STATEP(name, VA_NARGS(__VA_ARGS__), __VA_ARGS__)
/* args */
#define dec1(a) ref a;
#define dec2(a,b) dec1(a) ref b;
#define dec3(a,b,c) dec2(a, b) ref c;
#define dec4(a,b,c,d) dec3(a,b,c) ref d;
#define dec5(a,b,c,d,e) dec4(a,b,c,d) ref e;
#define dec6(a,b,c,d,e,f) dec5(a,b,c,d,e) ref f;
#define dec7(a,b,c,d,e,f,g) dec6(a,b,c,d,e,f)ref g;
#define dec8(a,b,c,d,e,f,g,h) dec7(a,b,c,d,e,f,g) ref h;
#define ref1(a) ref a
#define ref2(a,b) ref1(a), ref b
#define ref3(a,b,c) ref2(a,b), ref c
#define ref4(a,b,c,d) ref3(a,b,c), ref d
#define ref5(a,b,c,d,e) ref4(a,b,c,d), ref e
#define ref6(a,b,c,d,e,f) ref5(a,b,c,d,e), ref f
#define ref7(a,b,c,d,e,f,g) ref6(a,b,c,d,e,f), ref g
#define ref8(a,b,c,d,e,f,g, h) ref7(a,b,c,d,e,f,g), ref h
#define con1(a) this->a = a;
#define con2(a,b) con1(a) this->b = b;
#define con3(a,b,c) con2(a,b) this->c = c;
#define con4(a,b,c,d) con3(a,b,c) this->d = d;
#define con5(a,b,c,d,e) con4(a,b,c,d) this->e = e;
#define con6(a,b,c,d,e,f) con5(a,b,c,d,e) this->f = f;
#define con7(a,b,c,d,e,f,g) con6(a,b,c,d,e,f) this->g = g;
#define con8(a,b,c,d,e,f,g,h) con7(a,b,c,d,e,f,g) this->h = h;

所以如下:

/* 2 args */
SET_STATE(FunctorAA, foo, bar)
/* 3 args */
SET_STATE(FunctorBB, foo, bar, baz)
/* 4 args */    
SET_STATE(FunctorCC, foo, bar, baz, qux)

将产生:

ref foo; ref bar; FunctorAA(ref foo, ref bar) { this->foo = foo; this->bar = bar; }
ref foo; ref bar; ref baz; FunctorBB(ref foo, ref bar, ref baz) { this->foo = foo; this->bar = bar; this->baz = baz; }
ref foo; ref bar; ref baz; ref qux; FunctorCC(ref foo, ref bar, ref baz, ref qux) { this->foo = foo; this->bar = bar; this->baz = baz; this->qux = qux; }

注意:您可以按照明显的模式继续参数的数量。

【讨论】:

  • 哪部分不便携?
  • __VA_ARGS__ 是 C99 扩展,因此可能会或可能不会在 C++ 编译器预处理器中实现。
  • @Hamza Yerlikaya 我更新了我的代码,因此不需要参数的数量,使用链接中的一些技巧(在我的回答中)。
  • 我说该解决方案不可移植,仅适用于 GCC。
  • 自己没有测试,但我认为这个页面建议否则重新 MSVC:msdn.microsoft.com/en-us/library/ms177415.aspx
猜你喜欢
  • 2010-12-24
  • 2022-11-13
  • 1970-01-01
  • 1970-01-01
  • 2016-09-20
  • 2011-09-11
  • 1970-01-01
  • 2013-05-21
相关资源
最近更新 更多