-3

I have to define new instances of a type Inst with some arguments using the syntax NEWNSTANCE where NEWINSTANCE is a macro. It is clear that with the follow code the compiler will complain about a redefinition of ex but I have to follow this syntax.

// error redefinition ok very clear

#define NEWINSTANCE   Inst ex(…)

int main() {
    NEWINSTANCE;
    NEWINSTANCE;
    NEWINSTANCE;
}

I can't write NEWINSTANCE(name) to get inst name(…). Now I want to create “random” names for new instances. I don't care about the specific names.

Is possible to write something like ex ## __LINE__ (…) to have something like Inst ex1(…), Inst ex2(…) and multiple of them?

I am thinking of something like this but it is not working as expected.

#define NEWINSTANCE   Inst ex ## __LINE__ (…)

int main() {
    NEWINSTANCE; // Inst ex6(…)
    NEWINSTANCE; // Inst ex7(…)
    NEWINSTANCE; // Inst ex8(…)
}
5gon12eder
  • 24,280
  • 5
  • 45
  • 92
user2926018
  • 11
  • 1
  • 6
  • 2
    Please do not do this - the variable names will change at a whim. Why not just type them out and give them meaningful names. – Ed Heal Jan 04 '16 at 13:48
  • 1
    Please please please, don't do this. If I saw this at work, I would delete this file and rewrite it. – erip Jan 04 '16 at 13:49
  • 2
    If you do this, how would you use these newly created variables? You probably need just an array or a `std::vector` – ForceBru Jan 04 '16 at 13:50
  • 2
    just don't. if you need more than one instance use a vector or another container, or even a c array is better than a macro... – user1810087 Jan 04 '16 at 13:52
  • 2
    the most important question: **why?** – bolov Jan 04 '16 at 13:54

2 Answers2

1

There is the __COUNTER__ macro if you're using GCC.

Usage example:

#define XCONCAT(x, y) x##y
#define CONCAT(x, y) XCONCAT(x, y)
#define NEWINSTANCE int CONCAT(name, __COUNTER__)

int main(){
    NEWINSTANCE;
    NEWINSTANCE;
    NEWINSTANCE;
}

This code declares three integers with names name0, name1 and name2.

Since this has some downvotes, I'll expand on one potential use case for this kind of counters - compile time assertion:

#define XCONCAT( x, y ) x##y
#define CONCAT( x, y ) XCONCAT( x, y )
#define NEWINSTANCE(name)   CONCAT(name, __COUNTER__)

#define COMPILE_TIME_ASSERT(condition) \
    int NEWINSTANCE(assert_variable_)[(condition) - 1];

COMPILE_TIME_ASSERT(1 > 0);
COMPILE_TIME_ASSERT(2 > 1);

The benefit is that one does not have to introduce dummy variable names or put the macros in a function to rely on scoping rules to avoid multiple definitions.

The reason why you need the XCONCANT thing in the first line is desribed in, for example, this SO answer.

Community
  • 1
  • 1
kfx
  • 8,136
  • 3
  • 28
  • 52
  • Good luck when you come back in a few months time to try to debug this code – Ed Heal Jan 04 '16 at 13:52
  • 1
    @EdHeal few months? try next week – bolov Jan 04 '16 at 13:52
  • @bolov - I was being a bit optimistic. – Ed Heal Jan 04 '16 at 13:53
  • Guys, this is not a coding review site. – kfx Jan 04 '16 at 13:54
  • 2
    This is the correct answer to the question which was asking “how”. The fact that you (probably correctly) think that doing this is a bad idea in the first place is a poor reason to down-vote a technically correct answer. @kfx: You might want to improve your answer by explaining why the double expansion is needed. It seems that this is the bit that wasn't clear to the OP. – 5gon12eder Jan 04 '16 at 13:58
  • The compile-time assert was better handled using `static_assert` or – prior to C++11 – something like `template void() compile_time_assert_impl() { int dummy[2 * static_cast(Condition) - 1]; (void) dummy; }` and `#define COMPILE_TIME_ASSERT(Condition) compile_time_assert_impl< (Condition) >()`. No need for a randomly named variable which could cause ODR violations when used in header files. – 5gon12eder Jan 04 '16 at 14:13
  • @kfx the first code works greatly thank you very match! – user2926018 Jan 04 '16 at 16:03
1

While there might be a way to do that (see kfx's answer), I don't believe there is ever a reason to do it.

Consider what you think you need the macro for. What you want is simply a number of instances of a type. Instead of the macro kludge, I recommend using Inst ex[3]. You get exactly as many instances as you need, the program is easier to understand, and debug, and is more concise. Also, you can access the variables through the indices of the array which is something that you can't do when the variables are named randomly.

eerorika
  • 232,697
  • 12
  • 197
  • 326