迭代可变参数宏参数

问题描述

| 我正在以编程方式生成一堆函子,为了使所生成代码更具可读性,我试图提出一个宏,该宏将在下面扩展行,
SET_STATE(FunctorA,a,b);

ref a;
ref b;
FunctorA(ref a,ref b){
   this->a = a;
   this->b = b;
}
基本上它将扩展到第一个参数构造函数。可变参数部分是构造函数的参数数量。是否可以在宏内部循环并在预处理期间生成代码,即使对于这种特殊情况没有意义,但我有一些函子可以访问20个左右的变量,因此可以清理很多我生成代码。 所有参数的类型相同,只有名称不同。     

解决方法

        使用在此链接中找到的欺骗方法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,...) SET_STATEGENERATE(name,__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,c,d) dec3(a,c) ref d;
#define dec5(a,d,e) dec4(a,d) ref e;
#define dec6(a,e,f) dec5(a,e) ref f;
#define dec7(a,f,g) dec6(a,f)ref g;
#define dec8(a,g,h) dec7(a,g) ref h;
#define ref1(a) ref a
#define ref2(a,b) ref1(a),ref b
#define ref3(a,c) ref2(a,b),ref c
#define ref4(a,d) ref3(a,c),ref d
#define ref5(a,e) ref4(a,d),ref e
#define ref6(a,f) ref5(a,e),ref f
#define ref7(a,g) ref6(a,f),ref g
#define ref8(a,h) ref7(a,g),ref h
#define con1(a) this->a = a;
#define con2(a,b) con1(a) this->b = b;
#define con3(a,c) con2(a,b) this->c = c;
#define con4(a,d) con3(a,c) this->d = d;
#define con5(a,e) con4(a,d) this->e = e;
#define con6(a,f) con5(a,e) this->f = f;
#define con7(a,g) con6(a,f) this->g = g;
#define con8(a,h) con7(a,g) this->h = h;
因此,以下内容:
/* 2 args */
SET_STATE(FunctorAA,foo,bar)
/* 3 args */
SET_STATE(FunctorBB,bar,baz)
/* 4 args */    
SET_STATE(FunctorCC,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 baz,ref qux) { this->foo = foo; this->bar = bar; this->baz = baz; this->qux = qux; }
注意:您可以按照显而易见的模式继续增加参数的数量。     ,        如果允许
boost::preprocessor
SEQ
表示(
(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,i,elem ) BOOST_PP_COMMA_IF( i ) ref elem
#define DEF_ASSIGN( r,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; }
在我的环境中