我怎样写的 - 环QUOT递归;重复"宏来生成C code与CPP preprocessor? [英] How do I write a recursive for-loop "repeat" macro to generate C code with the CPP preprocessor?

查看:112
本文介绍了我怎样写的 - 环QUOT递归;重复"宏来生成C code与CPP preprocessor?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要强制preprocessor做一些自动code代我。我并不需要太多:只是一个简单的for循环包含另外一个for循环[1]

I want to force the preprocessor to do some automatic code generation for me. I don't need much: just a simple for-loop that contains another for-loop.[1]

我读过,我可以对宏展开,而不再傻笑当蓝色油漆接触所有。一个很好的一天我甚至可以解释为什么人们需要的宏多层生成带有标记粘贴函数名。其实我已经得到了for循环的工作。但是,当涉及到把一个循环的循环中,我降低到与DEFER,EVAL随机洒,阻挠,并希望最好的。

I've read all that I can about macro expansion, and no longer giggle when the blue paint comes up. On a good day I can even explain why one needs multiple layers of macros to generate a function name with token pasting. I've actually got the for-loop working. But when it comes to putting a loop within a loop, I'm reduced to sprinkling randomly with DEFER, EVAL and OBSTRUCT and hoping for the best.

我不会被调用的原因而却步。我真的想用标准C preprocessor做到这一点。我保证,不管结果如何,无论是我,我的雇主,也不是我的继承人会告你的技术弊端。我保证我不会让任何人来维持code,甚至可以查看它,没有适当的安全防护眼镜。 pretend,如果你想的,我只是问了理论上的意义。或者说,我唯一的其他选择是使用M4:对于如果CPP递归宏淫,肯定是M4整鸡。

I will not be deterred by calls to reason. I really do want to do this with the standard C preprocessor. I promise that regardless of outcome, neither I, my employer, nor my heirs will sue you for technological malpractice. I promise I won't allow anyone else to maintain the code, or even view it, without appropriate safety glasses. Pretend if you'd like that I'm just asking out of theoretical interest. Or that my only other option is using M4: for if recursive macros in CPP are kinky, certainly M4 is the whole chicken.

我已经找到了最好的参考材料是一个9岁的Usenet线程:
http://comp.std.c.narkive.com/5WbJfCof/double -cpp膨胀

The best reference material I've found is a 9-year-old Usenet thread: http://comp.std.c.narkive.com/5WbJfCof/double-cpp-expansion

它开始题外话,在语气上有些小气和好斗,而且是在我头上的方式。但我认为我所寻求的答案是那里的地方。

It starts off-topic, is somewhat petty and combative in tone, and is way over my head. But I think the answer I seek is in there somewhere.

下一个最好的是所谓的披风一个CPP滥用头文件:
https://github.com/pfultz2/Cloak/wiki/C-$p$pprocessor-tricks,-tips,-and-idioms

The next best is documentation for a CPP abusing header called Cloak: https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms

这需要一个稍微不同的方式来迭代,或许将成为我的需要,而不是。但它也是一个很好的概述。

It takes a somewhat different approach to iteration, and perhaps would serve my needs instead. But it's also a good overview.

下面是一些删节code,显示在那里我卡住了。

Here's some cut-down code to show where I'm stuck.

repeat.h:

#define REPEAT(macro, times, start_n, next_func, next_arg, macro_args...) \
    _REPEAT_ ## times(macro, start_n, next_func, next_arg, ## macro_args)

#define REPEAT_ADD_ONE(macro, times, start_n, macro_args... )                    \
    REPEAT(macro, times, start_n, _REPEAT_ADD_ONE, 0, ## macro_args)

#define _REPEAT_ADD_ONE(n, ignore...) _REPEAT_ADD_ONE_ ## n

#define _REPEAT_0(args...)  /* empty */
#define _REPEAT_1(macro, n, func, i, args...) macro(n, ## args) 
#define _REPEAT_2(m, n, f, i, a...) m(n, ## a); _REPEAT_1(m, f(n, i), f, i, ## a)
#define _REPEAT_3(m, n, f, i, a...) m(n, ## a); _REPEAT_2(m, f(n, i), f, i, ## a)
#define _REPEAT_4(m, n, f, i, a...) m(n, ## a); _REPEAT_3(m, f(n, i), f, i, ## a)
#define _REPEAT_5(m, n, f, i, a...) m(n, ## a); _REPEAT_4(m, f(n, i), f, i, ## a)
#define _REPEAT_6(m, n, f, i, a...) m(n, ## a); _REPEAT_5(m, f(n, i), f, i, ## a)
#define _REPEAT_7(m, n, f, i, a...) m(n, ## a); _REPEAT_6(m, f(n, i), f, i, ## a)
#define _REPEAT_8(m, n, f, i, a...) m(n, ## a); _REPEAT_7(m, f(n, i), f, i, ## a)
#define _REPEAT_9(m, n, f, i, a...) m(n, ## a); _REPEAT_8(m, f(n, i), f, i, ## a)
#define _REPEAT_10(m, n, f, i, a...) m(n, ## a); _REPEAT_9(m, f(n, i), f, i, ## a)

#define _REPEAT_ADD_ONE_0 1
#define _REPEAT_ADD_ONE_1 2
#define _REPEAT_ADD_ONE_2 3
#define _REPEAT_ADD_ONE_3 4
#define _REPEAT_ADD_ONE_4 5
#define _REPEAT_ADD_ONE_5 6
#define _REPEAT_ADD_ONE_6 7
#define _REPEAT_ADD_ONE_7 8
#define _REPEAT_ADD_ONE_8 9
#define _REPEAT_ADD_ONE_9 10
#define _REPEAT_ADD_ONE_10 11

#define _REPEAT_ADD_0(x) x
#define _REPEAT_ADD_1(x) _REPEAT_ADD_ONE(x)
#define _REPEAT_ADD_2(x) _REPEAT_ADD_1(_REPEAT_ADD_ONE(x))
#define _REPEAT_ADD_3(x) _REPEAT_ADD_2(_REPEAT_ADD_ONE(x))
#define _REPEAT_ADD_4(x) _REPEAT_ADD_3(_REPEAT_ADD_ONE(x))
#define _REPEAT_ADD_5(x) _REPEAT_ADD_4(_REPEAT_ADD_ONE(x))
#define _REPEAT_ADD_6(x) _REPEAT_ADD_5(_REPEAT_ADD_ONE(x))
#define _REPEAT_ADD_7(x) _REPEAT_ADD_6(_REPEAT_ADD_ONE(x))
#define _REPEAT_ADD_8(x) _REPEAT_ADD_7(_REPEAT_ADD_ONE(x))
#define _REPEAT_ADD_9(x) _REPEAT_ADD_8(_REPEAT_ADD_ONE(x))
#define _REPEAT_ADD_10(x) _REPEAT_ADD_9(_REPEAT_ADD_ONE(x))

sample.c文件:

sample.c:

#include "repeat.h"

#define INNER_MACRO(inner, outer) if (inner == outer) printf("Match\n")
#define INNER_BLOCK  { if (inner == outer) printf("Match\n"); }

#define OUTER_MACRO_INNER_MACRO(outer) REPEAT_ADD_ONE(INNER_MACRO, 3, 0, outer)
#define OUTER_BLOCK_INNER_MACRO { REPEAT_ADD_ONE(INNER_MACRO, 3, 0, outer); }
#define OUTER_MACRO_INNER_BLOCK(outer) REPEAT_ADD_ONE(INNER_BLOCK, 3, 0, outer)
#define OUTER_BLOCK_INNER_BLOCK { REPEAT_ADD_ONE(INNER_BLOCK, 3, 0, outer); }

void outer_macro_inner_macro() {
    REPEAT_ADD_ONE(OUTER_MACRO_INNER_MACRO, 2, 1);
}

void outer_macro_inner_block() {
    REPEAT_ADD_ONE(OUTER_MACRO_INNER_BLOCK, 2, 1);
}

void outer_block_inner_macro() {
    REPEAT_ADD_ONE(OUTER_BLOCK_INNER_MACRO, 2, 1);
}

void outer_block_inner_block() {
    REPEAT_ADD_ONE(OUTER_BLOCK_INNER_BLOCK, 2, 1);
}

sample.c文件我展示了接近我想要的四个变体。但没有一个是令人信服。下面是我得到与输出CPP sample.c文件> out.c;的astyle out.c;

In sample.c I've shown four variations that come close to what I want. But none are quite there. Here's what I get as output with "cpp sample.c > out.c; astyle out.c;"

void outer_macro_inner_macro() {
    REPEAT_ADD_ONE(INNER_MACRO, 3, 0, 1);
    REPEAT_ADD_ONE(INNER_MACRO, 3, 0, 2);
}

void outer_macro_inner_block() {
    REPEAT_ADD_ONE({ if (inner == outer) printf("Match\n"); }, 3, 0, 1);
    REPEAT_ADD_ONE({ if (inner == outer) printf("Match\n"); }, 3, 0, 2);
}

void outer_block_inner_macro() {
    {
        if (0 == outer) printf("Match\n");
        if (1 == outer) printf("Match\n");
        if (2 == outer) printf("Match\n");
    }(1);
    {
        if (0 == outer) printf("Match\n");
        if (1 == outer) printf("Match\n");
        if (2 == outer) printf("Match\n");
    }(2);
}

void outer_block_inner_block() {
    { {
            if (inner == outer) printf("Match\n");
        }(0, outer);
        {
            if (inner == outer) printf("Match\n");
        }(1, outer);
        {
            if (inner == outer) printf("Match\n");
        }(2, outer);
    }(1);
    { {
            if (inner == outer) printf("Match\n");
        }(0, outer);
        {
            if (inner == outer) printf("Match\n");
        }(1, outer);
        {
            if (inner == outer) printf("Match\n");
        }(2, outer);
    }(2);
}

和这里的输出我想要得到,而不是:

And here's the output I want to get instead:

void desired_results() {
   {
       if (0 == 1) printf("Match\n");
       if (1 == 1) printf("Match\n");
       if (2 == 1) printf("Match\n");
   };
   {
       if (0 == 2) printf("Match\n");
       if (1 == 2) printf("Match\n");
       if (2 == 2) printf("Match\n");
   };
}

从本质上讲,我可以得到的东西的工作,如果我使用块作为外循环体,但如果我用一个函数宏。但我需要使用宏与参数,以便循环体可以使用循环计数器作为常数,而不是作为一个变量。

Essentially, I can get things to work if I use a block as the outer loop body, but not if I use a function-like macro. But I need to use a macro with arguments so that the loop bodies can use the loop counter as a constant instead of as a variable.

与宏观问题 - 宏观调控的方式是,以REPEAT_ADD_ONE内递归调用()不扩大。答案似乎是推迟内环的扩张创造了外环后到,然后迫使另一路经展开的内部循环。但由于某些原因,我的随机猴子的方式,目前尚未产生一个解决方案...

The problem with the "macro"-"macro" manner is that the inner recursive call to REPEAT_ADD_ONE() is not expanded. The answer would seem to be deferring the expansion of the inner loop until after the outer loop is created, and then forcing another pass that expands the inner loop. But for some reason my "random monkey" approach to that hasn't yet produced a solution...

[1]低调之意。

推荐答案

的Vesa Karvonen的订单式图书馆/语言绝对可以为你做这个。它实现了无限制的递归和在C preprocessor循环,并作为一个非常酷的奖金礼服它与一个适当的编程语言的漂亮简洁的语法(澄清:这不是一个替代preprocessor,这只是做标记粘贴的的很多的保持其关键字短,它仍然是纯CPP)。

Vesa Karvonen's "Order" library/language can definitely do this for you. It implements unrestricted recursion and looping in the C preprocessor, and as a really cool bonus dresses it up with the nice concise syntax of a "proper" programming language (to clarify: this is not an alternative preprocessor, it just does a lot of token-pasting to keep its keywords short. It is still pure CPP).

它使用一个相当不同的技术,转换您元程序到CPS和然后将它们传递给一个的具有潜在的步骤万亿,并在严格的线性的方式执行元程序单的循环构造。因此,循环和递归函数可以嵌套深深只要你喜欢,因为他们没有单独的驱动程序需要互动和油漆对方蓝色的。

It uses a rather different technique, converting your metaprograms to CPS and then passing them to a single loop construct that has potentially trillions of steps, and executes the metaprogram in a strictly linear fashion. Loops and recursive functions can therefore be nested as deeply as you like because they don't have separate drivers that need to interact and paint each other blue.

是真的,有人实施了一个完整的虚拟机和跨preTER使用CPP宏。它的恐吓。

Yes really, someone implemented a full virtual machine and interpreter using CPP macros. It's intimidating.

(编辑:尝试存档版本如果罗塞塔code已停止为你工作了。)

( try the archived version if Rosetta Code has stopped working for you too.)

这篇关于我怎样写的 - 环QUOT递归;重复"宏来生成C code与CPP preprocessor?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆