How to generate random variable names in C++ using macros?

I'm creating a macro in C++ that declares a variable and assigns some value to it. Depending on how the macro is used, the second occurrence of the macro can override the value of the first variable. For instance:

#define MY_MACRO int my_variable_[random-number-here] = getCurrentTime();

The other motivation to use that is to avoid selecting certain name to the variable so that it be the same as a name eventually chosen by the developer using the macro.

Is there a way to generate random variable names inside a macro in C++?

-- Edit --

I mean unique but also random once I can use my macro twice in a block and in this case it will generate something like:

int unique_variable_name;
...
int unique_variable_name;

In this case, to be unique both variable names have to be random generated.


Solution 1:

Try the following:

// One level of macro indirection is required in order to resolve __COUNTER__,
// and get varname1 instead of varname__COUNTER__.
#define CONCAT(a, b) CONCAT_INNER(a, b)
#define CONCAT_INNER(a, b) a ## b

#define UNIQUE_NAME(base) CONCAT(base, __COUNTER__)

void main() {
  int UNIQUE_NAME(foo) = 123;  // int foo0 = 123;
  std::cout << foo0;           // prints "123"
}

__COUNTER__ may have portability issues. If this is a problem, you can use __LINE__ instead and as long as you aren't calling the macro more than once per line or sharing the names across compilation units, you will be just fine.

Solution 2:

Add M4 to your build flow? This macro language has some stateful capabilities, and can successfully be intermingled with CPP macros. This is probably not a standard way to generate unique names in a C environment, though I've been able to sucessfully use it in such a manner.

You probably do not not want random, BTW, based on the way you posed your question. You want unique.

You could use __FILE__ and __LINE__ in the macro expansion to get you the uniqueness you seem to be going for... those metavariables get defined within the source file context, so be careful to make sure you get what you are looking for (e.g., perils of more than one macro on the same line).

Solution 3:

use __COUNTER__ (works on gcc4.8, clang 3.5 and Intel icc v13, MSVC 2015)

#define CONCAT_(x,y) x##y
#define CONCAT(x,y) CONCAT_(x,y)
#define uniquename static bool CONCAT(sb_, __COUNTER__) = false

Solution 4:

Generating unique names in the preprocessor is difficult. The closest you can get is to mangle __FILE__ and __LINE__ into the symbol as popcnt suggests. If you really need to generate unique global symbol names, then I would follow his suggestion about using something like M4 or a Perl script in your build system instead.

You might not need unique names. If your macro can impose a new scope, then you can use the same name since it will simply shadow other definitions. I usually follow the common advice of wrapping macros in do { ... } while (0) loops. This only works for macros which are statements - not expressions. The macro can update variables using output parameters. For example:

#define CALC_TIME_SINCE(t0, OUT) do { \
     std::time_t _tNow = std::time(NULL); \
     (OUT) = _tNow - (t0); \
} while (0)

If you follow a few rules, you are usually pretty safe:

  1. Use leading underscores or similar naming conventions for symbols defined within the macro. This will prevent problems associated with a parameter using the same symbol from occurring.
  2. Only use the input parameters once and always surround them with parentheses. This is the only way to make macros work with expressions as input.
  3. Use the do { ... } while (0) idiom to ensure that the macro is only used as a statement and to avoid other textual replacement problems.

Solution 5:

Instead of having the preprocesser create a name, you could possibly let the macro user give you a name.

#define MY_MACRO(varname) int varname = getCurrentTime();