迭代c ++宏“列表”以生成代码

时间:2014-04-04 19:08:57

标签: c++ macros

我想写一些c ++宏代码来转换:

#define FRUITS Apple Banana Plum
EXPAND(FRUITS)

成:

void eat(Apple& instanceApple);
void eat(Banana& instanceBanana);
void eat(Plum& instancePlum);

是否可以编写EXPAND()函数来实现我的目标?

我意识到这看起来不像是一个好的编程实践,但我必须链接到具有特定接口的第三方库,并且这样做的能力将允许我在我自己的代码中避免大的重复代码块

编辑:稍微改变了我的玩具示例。

2 个答案:

答案 0 :(得分:3)

我并不是说这对可读性有很大帮助,但它使用Boost.Preprocessor做你想做的事情:

#define DECLARE_VAR(r, data, type) type BOOST_PP_CAT(instance,type);
#define EXPAND(seq) BOOST_PP_SEQ_FOR_EACH(DECLARE_VAR,,seq)

现在您可以按如下方式定义水果列表:

#define FRUITS (Apple)(Banana)(Plum)

然后您可以使用EXPAND(FRUITS)生成变量声明。有关完整示例see here

根据要求,每行打印一个水果的技术相同:

#include <iostream>
#include <boost/preprocessor.hpp>

#define PER_LINE(r, data, type) BOOST_PP_STRINGIZE(type) "\n"
#define EXPAND(seq) BOOST_PP_SEQ_FOR_EACH(PER_LINE,,seq)

#define FRUITS (Apple)(Banana)(Plum)

int main() {
    std::cout << EXPAND(FRUITS);
}

答案 1 :(得分:0)

没有时间解释,但我刚刚做了这个:

struct A
{
  int i;
  A(){i=1;}
  void quack() {std::cout << "A" << i << std::endl;}
};

struct B
{
  int i;
  B(){i=2;}
  void quack() {std::cout << "B" << i << std::endl;}
};
struct C
{
  int i;
  C(){i=3;}
  void quack() {std::cout << "C" << i << std::endl;}
};

#include <tuple>
std::tuple<A,B,C> tupl;


struct quacker
{
  template <typename T>
void operator()(T& t)
{
  t.quack();
}
};

template <typename Q,std::size_t index, typename... Ts>
typename std::enable_if<
index < sizeof...(Ts) >::type foo_helper(Q q,std::tuple<Ts...>& ts)
{
  q(std::get<index>(ts));
  foo_helper<Q,index+1,Ts...>(q,ts);
}
template <typename Q,std::size_t index, typename... Ts>
typename std::enable_if<
index >= sizeof...(Ts) >::type foo_helper(Q q,std::tuple<Ts...>& ts)
{

}

template <typename Q, typename... Ts>
void foo(Q q,std::tuple<Ts...> ts)
{
  foo_helper<Q,0,Ts...>(q,ts);
}





int main(int argc,char** argv)
{

  foo(quacker(),tupl);
}