tags:

views:

381

answers:

9
+2  Q: 

C++ enum by step

I'm trying to write the equivalent of an enum in C++ going in steps of eight instead of one, like

enum
{
    foo,
    bar = 8,
    baz = 16,
};

There will be a lot of entries, new ones will be added at intervals, and for clarity they really want to be written in an order other than order of entry, so it would be nice not to have to keep updating all the numbers by hand. I've tried mucking around with macro preprocessor tricks, but no dice so far. Is there a way to do this that I'm overlooking?

A: 

int foo, bar, baz;

baz = 
8 + bar =  
8 + foo;
Disco
They won't be constant expressions then.
Pavel Minaev
That's the idea: he wants to be able to "slip" one in any time he wants and have it fit into the +8 scheme.
Disco
+3  A: 

I'm not quite sure what you're asking, but this approach will autogenerate values at steps of 8, and make it relatively easy to insert new values in the middle of the enum and have all the following values update to accomodate the change:

  enum
  {
     foo,
     bar = foo + 8,
     baz = bar + 8
  }

After editing to add a "newvalue" you would have:

  enum
  {
     foo,
     bar = foo + 8,
     newvalue = bar + 8,
     baz = newvalue + 8
  }

You could also use a "Step" constant so that you can (a) change your mind about the step later, and (b) stop anyone accidentally adding the wrong step:

  const int EnumStep = 8;

  enum
  {
     foo,
     bar = foo + EnumStep,
     baz = bar + EnumStep 
  }
Jason Williams
+23  A: 
#define NEXT_ENUM_MEMBER(NAME) \
    NAME##_dummy, \
    NAME = NAME##_dummy - 1 + 8

enum MyEnum {
   Foo,
   NEXT_ENUM_MEMBER(Bar),
   NEXT_ENUM_MEMBER(Baz),
   ...
};
Pavel Minaev
Nice solution ... didn't think of that.
Goz
Rats, you beat me to it! Nice solution.
Bids
Clever trick, +1
Johannes Schaub - litb
A: 
#define ENUM_ENTRY_PASTE( x )   x

#define ENUM_ENTRY_8_SPACING( x ) \
    x,  \
    ENUM_ENTRY_PASTE(x)2, \
    ENUM_ENTRY_PASTE(x)3, \
    ENUM_ENTRY_PASTE(x)4, \
    ENUM_ENTRY_PASTE(x)5, \
    ENUM_ENTRY_PASTE(x)6, \
    ENUM_ENTRY_PASTE(x)7, \
    ENUM_ENTRY_PASTE(x)8

Its not ideal as you'll have all those extras but you'll have your enums in the right place.

Goz
+1  A: 
sambowry
+3  A: 

You could do the following:

#define STEP 8
#define ADD_ENUM(X, M) X = STEP * (M)
enum {
    ADD_ENUM(Foo, 0),
    ADD_ENUM(Bar, 1),
    ADD_ENUM(Baz, 2),
    //.. and so on
};
Ashwin
A: 

Another approach which requires a separete header file for the enum, eg entries.h:

enum
{
    ENTRY(foo),
    ENTRY(bar),
    ENTRY(baz)
};

Then, you could use the following

#define ENTRY(E) _ ## E
#include "entries.h"
#undef ENTRY
#define ENTRY(E) E = _ ## E * 8
#include "entries.h"
#undef ENTRY

to generate

enum
{
    _foo,
    _bar,
    _baz
};

enum
{
   foo = _foo * 8,
   bar = _bar * 8,
   baz = _baz * 8
};
Christoph
+7  A: 

I prefer something like this:

enum {
    foo = (0 << 3),
    bar = (1 << 3),
    baz = (2 << 3),
};

It's not automated, but it doesn't require much thinking when adding a new enum constant.

Lee Baldwin
I like! .................
Hamish Grubijan
A: 

Yet another possibility that avoids using (MISRA-prohibited) ## operators or creating extra enums/entries would be to do:

#define USE_MYENUM(value) (value*8)

enum
{
    foo = 0,
    bar,
    baz
} MyEnum = bar;

CallFunction(USE_MYENUM(MyEnum));

Of course, it would probably be preferable to put USE_MYENUM (or more likely MyEnum*8) into CallFunction() so that the type checking is done.

Al