views:

1265

answers:

5

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.

A: 

While I don't think its even possible, you should seriously consider making a class out of this.

If you want a random element in a random array to hold a certain value, you can do this:

std::vector< std::vector<int> > m_vec;

Then wrap it in a class, so the developer can only set a number:

void set(int foo)
{
    m_vec[random()][random()] = foo;
}

Is there any reason why you want it a macro? Random variable name sounds dangerous, what if it picks something already defined somewhere else in the code?

mizipzor
Actually I don't "want" it a macro, but the problem to be solved is into a macro. Your answer gave me an idea, I have created a class to hold the values (managing a list instead of declaring a variable each time).
freitass
+5  A: 

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).

popcnt
There is also the __COUNTER__ macro which generates new integer every time it is invoked, but it is non-standard.
Adam Rosenfield
Whoa, SO has comment formatting now! Anyways, that should really be COUNTER with two underscores preceding and following it.
Adam Rosenfield
This won't work for me since I may use the macro more than once inside the same file and reference it later in another macro. The "__ COUNTER __" (I know it is all together) may work but I would need to know the current value of the counter without incrementing it.
freitass
could you not #define A_VAR UNIQUE_VAR_MACRO() \n int A_VAR = 1; printf("%x",A_VAR);.... #UNDEF A_VAR ??
KitsuneYMG
+3  A: 

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.
D.Shawley
Using leading underscores is not a good idea, as names thus generated may clash with implementation reserved names, and are in any case reserved themselves.
anon
Indeed. It's possible the macro's user might want to use a name like _tNow. I'll suggest using the full macro name as a prefix for the names used by the macro, in this case CALC_TIME_SINCE_tNow
TokenMacGuy
+1  A: 

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();
TokenMacGuy
+1  A: 

use __COUNTER__ if available

#define uniquename static bool sb_##__COUNTER__ = false;
benoit