17

While sounding nonsensical.....

I want a Constant where every time you use it it will increment by 1

int x;
int y;
x = INCREMENTING_CONSTANT;
y = INCREMENTING_CONSTANT;

where x == 1; and y == 2

Note I don't want y = INCREMENTING_CONSTANT+1 type solutions.

Basically I want to use it as a compile time unique ID ( generally it wouldn't be used in code like the example but inside another macro)

abelenky
  • 63,815
  • 23
  • 109
  • 159
Keith Nicholas
  • 43,549
  • 15
  • 93
  • 156

10 Answers10

11

If you just need something unique ID ish, can you use the __LINE__ preprocessor symbol? It's not what you're asking for, but it might work for your purposes.

Stephen Canon
  • 103,815
  • 19
  • 183
  • 269
10

It's not standard, but some compilers support the __COUNTER__ macro. See Has anyone ever had a use for the __COUNTER__ pre-processor macro?

Community
  • 1
  • 1
quinmars
  • 11,175
  • 8
  • 32
  • 41
9

You may be able to put something together using Boost.Preprocessor (Works with C) and BOOST_PP_COUNTER

Example given on the docs page:

#include <boost/preprocessor/slot/counter.hpp>   
BOOST_PP_COUNTER // 0

#include BOOST_PP_UPDATE_COUNTER()   
BOOST_PP_COUNTER // 1

#include BOOST_PP_UPDATE_COUNTER()  
BOOST_PP_COUNTER // 2

#include BOOST_PP_UPDATE_COUNTER()
BOOST_PP_COUNTER // 3

Translated into what you want

#include <boost/preprocessor/slot/counter.hpp> 

int x = BOOST_PP_COUNTER; // 0

#include BOOST_PP_UPDATE_COUNTER()   
int y = BOOST_PP_COUNTER;// 1

#include BOOST_PP_UPDATE_COUNTER()  
int z = BOOST_PP_COUNTER; // 2

You could also use slots (slightly more flexible at the cost of more code than the above solution):

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

#define BOOST_PP_VALUE 0 //ensure 0 to start
#include BOOST_PP_ASSIGN_SLOT(1) 
int a = BOOST_PP_SLOT(1); //0

#define BOOST_PP_VALUE 1 + BOOST_PP_SLOT(1)
#include BOOST_PP_ASSIGN_SLOT(1) 
int b = BOOST_PP_SLOT(1); //1
Yacoby
  • 54,544
  • 15
  • 116
  • 120
  • Weird construct `#include BOOST_PP_UPDATE_COUNTER()` - do you really have to include that every time the counter should be increased? Honestly, I don't consider this a very handy way and refrain from using this solution. – Michael Beer Apr 12 '21 at 06:58
3

In my case I wanted to have a system-wide unique key for each subsystem, but the selection of subsystems would depend on the person using the system. These needed to be 8-bit values because it's targeted at embedded systems.

This is what I came up with just now:

#define LAST_KEY -1

// SUB1_KEY definition
enum {
  SUB1_KEY_ORIGIN = LAST_KEY,
  SUB1_KEY,
};
#undef LAST_KEY
#define LAST_KEY SUB1_KEY

// SUB2_KEY definition
enum {
  SUB2_KEY_ORIGIN = LAST_KEY,
  SUB2_KEY,
};
#undef LAST_KEY
#define LAST_KEY SUB2_KEY

// SUB3_KEY definition
enum {
  SUB3_KEY_ORIGIN = LAST_KEY,
  SUB3_KEY,
};
#undef LAST_KEY
#define LAST_KEY SUB3_KEY

// ....

The challenge will be making sure that the include chain that brings in each of these blocks is compiled in the same order every time.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
1

I've often wished for compile-time variables. However, the easiest thing to do would just be to define constants for each one invididually.

The answer above me's thread problem could be solved by the use of a functionoid in some global state class or a similar sort of solution if you're using C rather than C++.

You could also try using an xmacro. Create a new file, let's call it xmacro.h

INCREMENTING_CONSTANT;
#define INCREMENTING_CONSTANT INCREMENTING_CONSTANT + 1

Then, in a standard header,

#define INCREMENTING_CONSTANT 0
#define USE_INCREMENTING_CONSTANT #include "xmacro.h"

const int x = USE_INCREMENTING_CONSTANT

I haven't tested this, but xmacros have some awesome power that regular macros can't use, like defs/undefs, and my gut says it should work. The preprocessor is powerful, but rather dumb, so it could fail.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • 4
    This won't work - the preprocessor doesn't see directives that result from macro expansion. – caf Apr 01 '10 at 11:04
  • I came upon this solution independently, tried it, and it doesn't work... which is why I'm here :-) – Watusimoto Apr 07 '18 at 19:01
1

Do you want x and y to be constants themselves? If so the easiest and cleanest thing to do may be to use an anonymous enumeration:

enum {
    x = 1,
    y
    /* Add new ones here. */
};

This means you need only add a new name to that list and it will be given the next integer value. This is a useful trick where you don't care what the values are (outside runtime), as long as their distinct. For instance, when assigning identifiers to controls in a GUI, you often see:

enum {
    button1_id = FIRST_USER_ID,
    button2_id,
    combo_id,
    ...
}

Some GUI frameworks provide a GetUserId() function that will generate a new one (using an internal static variable); but I think this happens at runtime. It's also a bit tedious to see so many calls to it in succession.

button1_id = GetUserId();
button2_id = GetUserId();
combo_id = GetUserId();
...
Edmund
  • 10,533
  • 3
  • 39
  • 57
  • sadly no, I can't use the enum thing, its completely unknown how many items there may be. – Keith Nicholas Apr 01 '10 at 02:41
  • I'm not sure why that's a problem. Why is it any harder to add a new item to an enumeration than it is to (say) add another line of code to initialise it to some constant, elsewhere? – Edmund Apr 01 '10 at 02:50
  • because the macro may appear at any point in the code. Most likely it will be in the body of a function.... and another Macro would be in the body of another function etc etc, there will be an arbitrary amount of references to the macro in many different functions. Each time the macro appears I want it to increment by 1 – Keith Nicholas Apr 01 '10 at 03:59
0

I've seen a couple of suggestions to use an enum here but nothing posted here seems to really solve the problem that was asked. The Boost approach is pretty hacky - it uses a massive workaround to redefine a single defined value:

https://github.com/boostorg/preprocessor/tree/master/include/boost/preprocessor/slot

Here's a possible solution using enum:

#define REGISTER_EVENT_HANDLER(name)  name,

enum {
#define APP_REGISTER_HANDLERS
#include "main.h"
#undef APP_REGISTER_HANDLERS
APP_MAX_HANDLERS
};

// ...sometime later (not really relevant but might be useful for someone)...

#define IF_RUN_HANDLER(name)  if (state == name) {
#define ENDIF_RUN_HANDLER  }

#define APP_RUN_HANDLERS
#include "main.h"
#undef APP_RUN_HANDLERS

Inside "main.h":

#include "libfile1.h";
#include "libfile2.h";
#include "libfile3.h";
#include "libfile4.h";
#include "libfile5.h";
...
#include "libfileN.h";

Inside each "libfile#.h" file:

#ifdef APP_REGISTER_HANDLERS
REGISTER_EVENT_HANDLER(my_uniquely_named_event_handler)
#endif

#ifdef APP_RUN_HANDLERS
IF_RUN_HANDLER(my_uniquely_named_event_handler)
...Do something here...
ENDIF_RUN_HANDLER
#endif

As long as the enum entries are uniquely named, they will be given unique IDs, which is kind of what the OP was after. The major feature is to #define, #include, and then #undef the earlier define at the correct points in the code. The same file can be included many times, so triggering portions of the file to emit code at various points allows each file to define multiple outputs based on which #define is currently active.

CubicleSoft
  • 2,274
  • 24
  • 20
-4

Well, it's not constant then, is it? ;)

You can do this with a function:

int id() {
  static int i = 0;
  return ++i;
}

x = id();
y = id();

As shown, this is not thread-safe. To do that you would need to protect this with a mutex, or use a compiler/platform-specific atomic incrementer.

Tim
  • 8,912
  • 3
  • 39
  • 57
  • well, compile time constant :) which is where your answer totally fails! :) hence my question, how to make an incrementing compile time constant! much like ____LINE____ changes depending what line of code you are on :) – Keith Nicholas Mar 31 '10 at 22:53
  • 1
    I don't think this is quite what he wants. This will generate a new value at run time each time the function is called. I think he wants the value to be calculate once at compile time, then the same value is used every time that line is run. – Mark Byers Mar 31 '10 at 22:53
-6

An "incrementing constant" is an oxymoron. You cannot do this at compile time.

richb
  • 4,716
  • 5
  • 24
  • 22
-6

Here's an ugly way to implement it.

static int _counter=0;
#define INCREMENTING_CONSTANT (_counter++)
JayM
  • 4,798
  • 1
  • 21
  • 15