-2

I use the following code to generate a list (used later in a x macro)


#define LIST_OF_VARIABLES \
    X(value1) \
    X(value2) \
    X(value3) \
    X(value4) \
    X(value5) \
    X(value6) \
    X(value7)

Is there a way to generate a list with a given size N. Such that the resulting list contains elements from value0 to valueN ?

Im using the following X macro

#define X(name)  unsigned long long int name;
    LIST_OF_VARIABLES
#undef X
#define X(name) name =idx;
    LIST_OF_VARIABLES
#undef X

and generates this output




 value1 =idx; value2 =idx; value3 =idx; value4 =idx; value5 =idx; value6 =idx; value7 =idx;


Solution thanks to M Oehm


//#################Q VAR GENERATION#################
#define VAR(P, NNN, NN, N) P##NNN##NN##N

#define NUM0(P, X, NNN, NN)                      X(VAR(P, NNN, NN, 0))
#define NUM1(P, X, NNN, NN) NUM0(P, X, NNN, NN) X(VAR(P, NNN, NN, 1))
#define NUM2(P, X, NNN, NN) NUM1(P, X, NNN, NN) X(VAR(P, NNN, NN, 2))
#define NUM3(P, X, NNN, NN) NUM2(P, X, NNN, NN) X(VAR(P, NNN, NN, 3))
#define NUM4(P, X, NNN, NN) NUM3(P, X, NNN, NN) X(VAR(P, NNN, NN, 4))
#define NUM5(P, X, NNN, NN) NUM4(P, X, NNN, NN) X(VAR(P, NNN, NN, 5))
#define NUM6(P, X, NNN, NN) NUM5(P, X, NNN, NN) X(VAR(P, NNN, NN, 6))
#define NUM7(P, X, NNN, NN) NUM6(P, X, NNN, NN) X(VAR(P, NNN, NN, 7))
#define NUM8(P, X, NNN, NN) NUM7(P, X, NNN, NN) X(VAR(P, NNN, NN, 8))
#define NUM9(P, X, NNN, NN) NUM8(P, X, NNN, NN) X(VAR(P, NNN, NN, 9))

#define NUM(P, X, NNN, NN, N) NUM##N(P, X, NNN, NN)

#define NNUM0(P, X, NNN, N)                      NUM(P, X, NNN, 0, N)
#define NNUM1(P, X, NNN, N) NNUM0(P, X, NNN, 9) NUM(P, X, NNN, 1, N)
#define NNUM2(P, X, NNN, N) NNUM1(P, X, NNN, 9) NUM(P, X, NNN, 2, N)
#define NNUM3(P, X, NNN, N) NNUM2(P, X, NNN, 9) NUM(P, X, NNN, 3, N)
#define NNUM4(P, X, NNN, N) NNUM3(P, X, NNN, 9) NUM(P, X, NNN, 4, N)
#define NNUM5(P, X, NNN, N) NNUM4(P, X, NNN, 9) NUM(P, X, NNN, 5, N)
#define NNUM6(P, X, NNN, N) NNUM5(P, X, NNN, 9) NUM(P, X, NNN, 6, N)
#define NNUM7(P, X, NNN, N) NNUM6(P, X, NNN, 9) NUM(P, X, NNN, 7, N)
#define NNUM8(P, X, NNN, N) NNUM7(P, X, NNN, 9) NUM(P, X, NNN, 8, N)
#define NNUM9(P, X, NNN, N) NNUM8(P, X, NNN, 9) NUM(P, X, NNN, 9, N)

#define NNUM(P, X, NNN, NN, N) NNUM##NN(P, X, NNN, N)

#define NNNUM0(P, X, NN, N)                      NNUM(P, X, 0, NN, N)
#define NNNUM1(P, X, NN, N) NNNUM0(P, X, 9, NN) NNUM(P, X, 1, NN, N)
#define NNNUM2(P, X, NN, N) NNNUM1(P, X, 9, NN) NNUM(P, X, 2, NN, N)
#define NNNUM3(P, X, NN, N) NNNUM2(P, X, 9, NN) NNUM(P, X, 3, NN, N)
#define NNNUM4(P, X, NN, N) NNNUM3(P, X, 9, NN) NNUM(P, X, 4, NN, N)
#define NNNUM5(P, X, NN, N) NNNUM4(P, X, 9, NN) NNUM(P, X, 5, NN, N)
#define NNNUM6(P, X, NN, N) NNNUM5(P, X, 9, NN) NNUM(P, X, 6, NN, N)
#define NNNUM7(P, X, NN, N) NNNUM6(P, X, 9, NN) NNUM(P, X, 7, NN, N)
#define NNNUM8(P, X, NN, N) NNNUM7(P, X, 9, NN) NNUM(P, X, 8, NN, N)
#define NNNUM9(P, X, NN, N) NNNUM8(P, X, 9, NN) NNUM(P, X, 9, NN, N)

#define NNNUM(P, X, NNN, NN, N) NNNUM##NNN(P, X, NN, N)

//#####################Q var count####################
#define QA(X) NNNUM(qA, X, 0, 1, 6)
#define QB(X) NNNUM(qB, X, 0, 1, 6)
//####################################################

#define INIT(A) unsigned long long int A=EMPTY_STATE_VALUE;
#define TEST(A)  res[0]=A;


//in code
    QB(INIT);
    QA(TEST);
sherif
  • 2,282
  • 19
  • 21

5 Answers5

2

First, I agree with John Bode's answer, in that I suspect what you're trying to accomplish can be done more elegantly with some other construct, rather than relying on preprocessor macros. Even if you disagree with the common wisdom that "macros are evil", they are nonetheless ugly, difficult to debug, and often error-prone and non-portable as well. My advice would be to take a different approach - preferably one that doesn't rely on preprocessor trickery.

Having said that, as pointed out here, there is a Boost preprocessor library that makes it possible to write preprocessor loops.

Here's an example (from this page on boost.org):

#include <boost/preprocessor/iteration/local.hpp>

template<int> struct sample;

#define BOOST_PP_LOCAL_MACRO(n) \
   template<> struct sample<n> { \
      enum { value = n }; \
   }; \
   /**/

#define BOOST_PP_LOCAL_LIMITS (1, 5)

#include BOOST_PP_LOCAL_ITERATE()
/* expands to...
template<> struct sample<1> { enum { value = 1 }; };
template<> struct sample<2> { enum { value = 2 }; };
template<> struct sample<3> { enum { value = 3 }; };
template<> struct sample<4> { enum { value = 4 }; };
template<> struct sample<5> { enum { value = 5 }; };
*/
Community
  • 1
  • 1
Mike Holt
  • 4,452
  • 1
  • 17
  • 24
  • I dont need many entries (<16) and its a small school project it would be less work to write it by hand as to create a automated tool +1 for the boost solution – sherif Jun 04 '14 at 08:12
1

Not within the preprocessor itself; all preprocessor definitions are recognized before macro expansion; IOW, you can't define a macro that expands into a #define and have that definition be recognized by the preprocessor.

You could write a small utility program that generates that macro, which you would save to your header file.

However...

Normally, when you need a bunch of variables of the same type and distinguished only by an ordinal (value0, value1, value2, ...), you'd use an array. Is there any particular reason why an array would not be useful in your case?

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • Yes as a matter of fact there is :D Im developing something for cuda and local arrays are stored in local memory which is slower as registers – sherif Jun 03 '14 at 19:46
  • @sherif: Makes sense. In that case, I'll repeat my suggestion above; write a small utility program that takes your min and max as arguments and have it generate a file containing the macro, which gets `#include`d as necessary. This could be automated as part of your build process. – John Bode Jun 03 '14 at 20:26
  • I dont need many entries (<16) and its a small school project it would be less work to write it by hand as to create a automated tool – sherif Jun 04 '14 at 08:11
1

Oh, it can be done in the preprocessor. Kind of. I don't think that the enumeration that is produced is useful or that the method is elegant, but doing things in the preprocessor always gives that sense of achievement. Like opening a baked-bean tin with a knitting needle. At three o'clock in the morning.

Anayway, here's an approach that lets you define N enumerated variables. You have to specify N as separate hundreds, tens and ones, though:

#define VAR(P, NNN, NN, N) P##NNN##NN##N

#define NUM0(P, X, NNN, NN)                      X(VAR(P, NNN, NN, 0))
#define NUM1(P, X, NNN, NN) NUM0(P, X, NNN, NN), X(VAR(P, NNN, NN, 1))
#define NUM2(P, X, NNN, NN) NUM1(P, X, NNN, NN), X(VAR(P, NNN, NN, 2))
#define NUM3(P, X, NNN, NN) NUM2(P, X, NNN, NN), X(VAR(P, NNN, NN, 3))
#define NUM4(P, X, NNN, NN) NUM3(P, X, NNN, NN), X(VAR(P, NNN, NN, 4))
#define NUM5(P, X, NNN, NN) NUM4(P, X, NNN, NN), X(VAR(P, NNN, NN, 5))
#define NUM6(P, X, NNN, NN) NUM5(P, X, NNN, NN), X(VAR(P, NNN, NN, 6))
#define NUM7(P, X, NNN, NN) NUM6(P, X, NNN, NN), X(VAR(P, NNN, NN, 7))
#define NUM8(P, X, NNN, NN) NUM7(P, X, NNN, NN), X(VAR(P, NNN, NN, 8))
#define NUM9(P, X, NNN, NN) NUM8(P, X, NNN, NN), X(VAR(P, NNN, NN, 9))

#define NUM(P, X, NNN, NN, N) NUM##N(P, X, NNN, NN)

#define NNUM0(P, X, NNN, N)                      NUM(P, X, NNN, 0, N)
#define NNUM1(P, X, NNN, N) NNUM0(P, X, NNN, 9), NUM(P, X, NNN, 1, N)
#define NNUM2(P, X, NNN, N) NNUM1(P, X, NNN, 9), NUM(P, X, NNN, 2, N)
#define NNUM3(P, X, NNN, N) NNUM2(P, X, NNN, 9), NUM(P, X, NNN, 3, N)
#define NNUM4(P, X, NNN, N) NNUM3(P, X, NNN, 9), NUM(P, X, NNN, 4, N)
#define NNUM5(P, X, NNN, N) NNUM4(P, X, NNN, 9), NUM(P, X, NNN, 5, N)
#define NNUM6(P, X, NNN, N) NNUM5(P, X, NNN, 9), NUM(P, X, NNN, 6, N)
#define NNUM7(P, X, NNN, N) NNUM6(P, X, NNN, 9), NUM(P, X, NNN, 7, N)
#define NNUM8(P, X, NNN, N) NNUM7(P, X, NNN, 9), NUM(P, X, NNN, 8, N)
#define NNUM9(P, X, NNN, N) NNUM8(P, X, NNN, 9), NUM(P, X, NNN, 9, N)

#define NNUM(P, X, NNN, NN, N) NNUM##NN(P, X, NNN, N)

#define NNNUM0(P, X, NN, N)                      NNUM(P, X, 0, NN, N)
#define NNNUM1(P, X, NN, N) NNNUM0(P, X, 9, NN), NNUM(P, X, 1, NN, N)
#define NNNUM2(P, X, NN, N) NNNUM1(P, X, 9, NN), NNUM(P, X, 2, NN, N)
#define NNNUM3(P, X, NN, N) NNNUM2(P, X, 9, NN), NNUM(P, X, 3, NN, N)
#define NNNUM4(P, X, NN, N) NNNUM3(P, X, 9, NN), NNUM(P, X, 4, NN, N)
#define NNNUM5(P, X, NN, N) NNNUM4(P, X, 9, NN), NNUM(P, X, 5, NN, N)
#define NNNUM6(P, X, NN, N) NNNUM5(P, X, 9, NN), NNUM(P, X, 6, NN, N)
#define NNNUM7(P, X, NN, N) NNNUM6(P, X, 9, NN), NNUM(P, X, 7, NN, N)
#define NNNUM8(P, X, NN, N) NNNUM7(P, X, 9, NN), NNUM(P, X, 8, NN, N)
#define NNNUM9(P, X, NN, N) NNNUM8(P, X, 9, NN), NNUM(P, X, 9, NN, N)

#define NNNUM(P, X, NNN, NN, N) NNNUM##NNN(P, X, NN, N)

You could then use it in an X macro like this:

#define ENUM(A) A
#define STRING1(A) #A
#define STRING(A) STRING1(A)

#define LIST_OF_VARIABLES(X) NNNUM(dalmatian, X, 1, 0, 0)

enum {
    LIST_OF_VARIABLES(ENUM)
};

const char *varname[] = {
    LIST_OF_VARIABLES(STRING)
}

This will generate 101 enum values called dalmatian000 through damtaian100 plus the corresponding string entities. They will be separated by commas; you can change this by deleting the top-level commas in the macro replacements.

The system can be extended for more than 1000 entries.

The macro is not useful for generating numbers, because the lower values will end up having leading zeros, which makes them octal constants. But it should be easy to generate hex constants.

M Oehm
  • 28,726
  • 3
  • 31
  • 42
0

No way, but you can add there a loop (if you know how to generate values):

#define LIST_OF_VARIABLES(low, high) for(int i=low; i <= high; i++) { X(i); };
Vitaly Dyatlov
  • 1,872
  • 14
  • 24
  • 1
    Not sure what the point of this would be. More than likely, the OP intends to use the `LIST_OF_VARIABLES` macro in file scope, in which case this would just produce compiler errors. Moreover, even if he intends to use the macro inside a function, it is unlikely that whatever his `X` macro is doing is going to generate list values that will exist anywhere but inside the `for` loop's scope. – Mike Holt Jun 03 '14 at 19:21
  • perhaps I misunderstood the question – Vitaly Dyatlov Jun 03 '14 at 19:29
  • Or perhaps I did. Whatever it is the OP is trying to accomplish, I doubt that a bunch of overly clever preprocessor trickery is going to lead him down a good path. Although, purely from a "can it be done?" perspective, I suspect there is a way (albeit undoubtedly kludgy), perhaps with recursive `#include` statements or the like. – Mike Holt Jun 03 '14 at 19:37
0

It's a little unclear what you mean by "list". I'm kind of assuming you want some kind of variable partition of something like

X(value0)
X(value1)
...
X(valuen)

but you can arbitrarily "chop off" values from the end, or possibly beginning, or both. The answer is no, but you can simulate it with something like:

values_x.h

#ifdef USE_VALUES_X_VALUE0
X(value0)
#endif
X(value1)
X(value2)
X(value3)
X(value4)
X(value5)
X(value6)
X(value7)
#ifdef USE_VALUES_X_TO_VALUEN
X(value8)
...
X(valuen)
#endif

So for list of variables you'd use this file something like:

#undef USE_VALUES_X_VALUE0
#undef USE_VALUES_X_TO_VALUEN
#define X(x_) unsigned long long int x_ = idx; // X-Macro code goes here
#include "values_x.h"

And that would be like LIST_OF_VARIABLES.

Another way you can do that is to have a code generation tool like GNU Autogen generate different X-Macros headers for you (basically removing the #include logic as shown above from the headers and putting it in the autogen template/data files).

ldav1s
  • 15,885
  • 2
  • 53
  • 56
  • Yes I need something like X(value0) X(value1) ...X(valuen) im trying to avoid the manual typing of each value I have updated the question – sherif Jun 03 '14 at 20:02