Macro increase value and then concatenate

2019-08-03 23:11发布

问题:

I want to create a recursive Macro the will create the "next" class.

Example:

#define PRINTME(indexNum) class m_##(indexNum+1) { }

The indexNum + 1 is evaluated as an int, and won't concatenate to the class name.

How can I cause the compiler to evaluate that, before concatenating?

回答1:

The simple answer is that you can't. The preprocessor generally deals in text and tokens; the only place arithmetic is carried out in in #if and #elif directives.

Also, macro expansion isn't recursive. During expansion, the macro being expanded is disabled, and is not available for further substitution.



回答2:

If you want to generate unique class names every time the PRINTME is invoked then, following is one way:

#define CONCATE1(X,Y) X##Y
#define CONCATE(X,Y)  CONCATE1(X,Y)

#define PRINTME class CONCATE(m_,__COUNTER__) {}

__COUNTER__ is an extension in gcc and I am not sure if it's present in other compilers. It's guaranteed that compiler will add 1 every time this macro is invoked.
(In this case, you cannot use __LINE__ or __FILE__ effectively.)

Demo.



回答3:

Well it is doable, based on your motivation and ability to endure ugly code. First off define increment macro:

#define PLUS_ONE(x) PLUS_ONE_##x

#define PLUS_ONE_0 1
#define PLUS_ONE_1 2
#define PLUS_ONE_2 3
#define PLUS_ONE_3 4
#define PLUS_ONE_4 5
#define PLUS_ONE_5 6
#define PLUS_ONE_7 8
#define PLUS_ONE_8 9
#define PLUS_ONE_9 10
// and so on...

You can't just use PLUS_ONE(x) in concatenation operation, since preprocessor won't expand it. There is a way, however - you can abuse the fact that the preprocessor expands variadic arguments.

// pass to variadic macro to expand an argument
#define PRINTME(indexNum)       PRINTME_PRIMITIVE(PLUS_ONE(indexNum))
// do concatenation
#define PRINTME_PRIMITIVE(...)  class m_ ## __VA_ARGS__ { }

Done!

PRINTME(1); // expands to class m_2 { };

Have you considered using templates instead?