4

I want to write the C macros which takes either an integer literal or something akin to an integer literal, and the name of another macro, and expands that other macro as many times as the value of the integer literal, with the index as an argument, e.g.

MAGIC(4, FUN) 

expands to

FUN(0) FUN(1) FUN(2) FUN(3) 

If, instead, I would have MORE_MAGIC which takes a range start and length, that would be even nicer:

e.g.

MORE_MAGIC(1, 3, FUN) 

expands to

FUN(1) FUN(2) FUN(3) 

Note:

  • I can live with the number of expansions being limited to, I dunno, 99, or 50, or something like that.
  • You cannot make assumptions regarding FUN. The needs to be generic. And no, this is not for manually unrolling for loops.
  • C-only solutions are the most welcome as well as solutions which require C++ (e.g. if you somehow use templates in your solution).
  • The total number of lines of a solution (including #include's but excluding comments) should preferably be modest. Say, no more than 200.
8
  • Why do you want this? How about expanding to a for loop? Commented May 22, 2016 at 22:37
  • "You cannot make assumptions regarding FUN" and "using templates" are fundamentally incompatible. By allowing the use of templates, you allow people to make assumptions about FUN. It sounds like you don't want to say why you want this because you think you know best, but the notes in your question already make me doubt that. Commented May 22, 2016 at 23:17
  • Also, editing a question to disqualify an existing answer that clearly provided exactly what you asked for is pretty much not done, and you should know that already. Commented May 22, 2016 at 23:18
  • @hvd: With due respect 1. It was an invalid answer to begin with. 2. It is done often when questions are misconstrued or when an OP has not been sufficiently clear about what exactly he is asking. Commented May 22, 2016 at 23:53
  • @hvd: I just meant to allow solutions to use templates (although I'm not sure that's actually useful) Commented May 22, 2016 at 23:55

2 Answers 2

9

Boost Preprocessor is an extensive library, focusing on such pre-processor magic.

It offers a macro called BOOST_PP_REPEAT_FROM_TO, which does exactly what you want.

Full reference is available here:
http://boost.org/libs/preprocessor

Sign up to request clarification or add additional context in comments.

5 Comments

Is it possible to extract just BOOST_PP_REPEAT_FROM_TO without all of the Boost Preprocessor library?
@einpoklum My understanding is that the Boost Preprocessor library is standalone and doesn't require the rest of Boost. I'm not sure if you can extract individual components from Boost Preprocessor, though.
Through the efforts of the "Modular Boost" project, the stand-alone version of PP is available here. It would be fairly hard to extract just REPEAT_FROM_TO, but you can include only the required bits with <boost/preprocessor/repetition/repeat_from_to.hpp>
(Replaced previous comment) @zah: I checked, and this solution requires at least 6647 lines of code (with Boost 1.60). Of course, it could theoretically be reduced further by hand-including only what's necessary.
@einpoklum, I wouldn't worry too much about it. The very little effects the preprocessor tricks have on compile times have always surprised me. They make a bit more sense when you consider how trivial text replacement is compared to the other things the compiler needs to do in order to arrive at the final executable code.
-2

What you want is basically an unrolled for loop... but you didn't say why you want that. You can make a macro that creates a for loop and trust the compiler to decide whether it's worth unrolling or not.

#include <stdio.h> #define PRINT_INT(i) printf("%d\n", i); #define MORE_MAGIC(start, end, function) for(int i = start; i <= end; i++) { function(i); } #define MAGIC(end, function) MORE_MAGIC(0, end, function) int main() { puts("MAGIC!"); MAGIC(3, PRINT_INT); puts("MORE_MAGIC!"); MORE_MAGIC(2, 6, PRINT_INT); return 0; } 

5 Comments

This does not answer my question. Also, see edit. Also, you're issuing a zillion printf instructions!
@einpoklum If you told us why you need this, and what some of those cases when a for loop will not do are, we could answer it better. The only thing I can think of is declaring variables, and if you want to declare so many numbered variables that you need a macro for it you should probably rethink why you need so many variables.
@einpoklum Not sure what you mean by "you're issuing a zillion printf instructions"; it prints 11 lines and they're just for demonstration purposes. Your edit doesn't seem to change the question much. If you don't want to say what this is for, your call, doesn't make much sense to me.
Suppose you're in a multi-threaded context. If you break up your printing over multiple printf instructions, this will all get jumbled.
@einpoklum I'd be interested in a demonstration of that.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.