Setting macro-variable-value in macro-function C++ - c++

I need to call a function which call a macro-function to change macro-value in runtime.
This code isn't compiled:
#define MY_MACRO 32
#define SET_MY_MACRO_VAL(IS_TRUE)(MY_MACRO=(IS_TRUE)?16:U32)
In function SET_MY_MACRO_VAL
> error: lvalue required as left operand of assignment
#define SET_MY_MACRO_VAL(IS_TRUE)(MY_MACRO=(IS_TRUE)?16:U32)
^
in expansion of macro 'SET_MY_MACRO_VAL'
SET_MY_MACRO_VAL(True);
^

Macro value are replaced BEFORE compile time by the preprocessor and do not exist at run time.
It is not a variable it is simply a way of using text for the value "32".
If you do this :
#define MY_MACRO 32
#define SET_MY_MACRO_VAL(IS_TRUE)(MY_MACRO=(IS_TRUE)?16:U32)
It will be expanded to this
#define MY_MACRO 32
#define SET_MY_MACRO_VAL(IS_TRUE)(32=(IS_TRUE)?16:U32)
What you can do is use a #define
#ifdef SET_MACRO_VAL_32
#define MY_MACRO 32
#else
#define MY_MACRO 16
#endif
Or use a conditionnal macro if you prefer
#if (IS_TRUE>0)
#define MY_MACRO 32
#else
#define MY_MACRO 16
#endif
Edit :
In C++, you shouldn't really need macro though. You can use template and / or constexpr variable for compile-time value. In C++17 you can even use constexpr if.

Related

Can `#ifdef` be used inside a macro?

I only found this related question, which isn't quite what I am looking for.
I used to have macros defined inside an #ifdef statement:
#ifdef DEBUG
# define PRINT_IF_DEBUGGING(format) printf(format);
# define PRINTF_IF_DEBUGGING(format, ...) printf(format, __VA_ARGS__);
#else
# define PRINT_IF_DEBUGGING(...)
# define PRINTF_IF_DEBUGGING(...)
#endif
Now, I want to do the inverse, to have the #ifdef statements inside the macros. Something like this:
#define PRINT_IF_DEBUGGING(format, ...) \
#if defined(DEBUG) print(format); #endif
#define PRINTF_IF_DEBUGGING(format, ...) \
#if defined(DEBUG) printf(format, __VA_ARGS__); #endif
However, I am having an issue using __VA_ARGS__ inside the #ifdef defined.
error: '#' is not followed by a macro parameter
#define PRINT_IF_DEBUGGING(format, ...)
error: '#' is not followed by a macro parameter
#define PRINTF_IF_DEBUGGING(format, ...)
warning: __VA_ARGS__ can only appear in the expansion of a C++11 variadic macro
#if defined(DEBUG) printf(format, __VA_ARGS__); #endif
Is this possible?
This should really be a comment, but I can't format that in a way that will allow me to say what I want to say, so I'm answering instead.
Anyway, just change this:
#if defined(DEBUG) print(format); #endif
to this:
#if defined(DEBUG)
print(format);
#endif
and so on, and that should fix it.
You can't use #ifdef inside of #define , so no, this is not possible. The first code you showed is the correct solution.
Using #ifdef inside of #define is not possible. But there are still ways you can detect wether or not a macro has been defined within a macro definition.
1. Solution
godbolt
#define CAT(a, b) CAT_IMPL(a, b)
#define CAT_IMPL(a, b) a ## b
#define IS_DEBUG_DEFINED() CHECK((CAT(CHECK_,DEBUG), 0, 1))
#define CHECK_DEBUG ~,~
#define CHECK(tup) CHECK_IMPL tup
#define CHECK_IMPL(a, b, c, ...) c
#define IIF(condition, true_value, false_value) CAT(IIF_,condition)(true_value, false_value)
#define IIF_0(true_value, false_value) false_value
#define IIF_1(true_value, false_value) true_value
#define PRINT_IF_DEBUGGING(format) IIF(IS_DEBUG_DEFINED(), PRINT_DEBUGGING, PRINT_NOT_DEBUGGING)(format)
// this will be used if DEBUG is defined:
#define PRINT_DEBUGGING(format) debugPrint(format)
// this will be used if DEBUG is NOT defined:
#define PRINT_NOT_DEBUGGING(format) print(format)
PRINT_IF_DEBUGGING(foo) will expand to:
if DEBUG is defined: debugPrint(foo)
if DEBUG is not defined: print(foo)
Example:
PRINT_IF_DEBUGGING("test1");
#define DEBUG
PRINT_IF_DEBUGGING("test2");
#undef DEBUG
PRINT_IF_DEBUGGING("test3");
would result in:
print("test1");
debugPrint("test2");
print("test3");
2. How IS_DEBUG_DEFINED() works
The fundamental trick behind this is to use concatenation - if the macro was defined it will be expanded, otherwise the token will be left unmodified by the preprocessor:
godbolt
#define CAT(a, b) CAT_IMPL(a, b)
#define CAT_IMPL(a, b) a ## b
// DEBUG NOT DEFINED:
CAT(CHECK_,DEBUG) // will expand to CHECK_DEBUG
// DEBUG DEFINED:
#define DEBUG 1234
CAT(CHECK_,DEBUG) // will expand to CHECK_1234
The first CAT will expand to CHECK_DEBUG, because DEBUG was not defined.
The second CAT however will expand to CHECK_1234, because DEBUG was defined and expanded to 1234 before the concatenation with CHECK_.
By defining a macro named CHECK_DEBUG we can change the result if the macro was not defined, e.g.:
godbolt
#define TEST CAT(CHECK_,DEBUG), 0, 1
#define CHECK_DEBUG ~,~
If DEBUG is not defined the result will be ~, ~, 0, 1 (4 comma-separated tokens)
If DEBUG is defined the result will be CHECK_, 0, 1 (3 comma-separated tokens)
Notice how we got 4 tokens in the first case, but only 3 tokens in the second.
Now all we need to do is take the 3rd token from that sequence (which will be 0 if DEBUG is not defined and 1 otherwise), for example with a simple macro that always returns the 3rd argument:
#define CHECK(a, b, c, ...) c
Putting it all together, this is what a full IS_DEBUG_DEFINED() could look like:
godbolt
#define CAT(a, b) CAT_IMPL(a, b)
#define CAT_IMPL(a, b) a ## b
#define IS_DEBUG_DEFINED() CHECK((CAT(CHECK_,DEBUG), 0, 1))
#define CHECK_DEBUG ~,~
#define CHECK(tup) CHECK_IMPL tup
#define CHECK_IMPL(a, b, c, ...) c
IS_DEBUG_DEFINED() will expand to 0 if DEBUG is not defined, and 1 if it is, e.g.:
IS_DEBUG_DEFINED() // -> 0
#define DEBUG
IS_DEBUG_DEFINED() // -> 1
#undef DEBUG
IS_DEBUG_DEFINED() // -> 0
With IS_DEBUG_DEFINED() you can then use a standard preprocessor IIF to change the behaviour of your macro depending on wether DEBUG is defined or not.
Example: godbolt
#define IIF(condition, true_value, false_value) CAT(IIF_,condition)(true_value, false_value)
#define IIF_0(true_value, false_value) false_value
#define IIF_1(true_value, false_value) true_value
#define PRINT_IF_DEBUGGING(format) IIF(IS_DEBUG_DEFINED(), PRINT_DEBUGGING, PRINT_NOT_DEBUGGING)(format)
// this will be used if DEBUG is defined:
#define PRINT_DEBUGGING(format) debugPrint(format)
// this will be used if DEBUG is NOT defined:
#define PRINT_NOT_DEBUGGING(format) print(format)
PRINT_IF_DEBUGGING("test"); // -> print("test");
#define DEBUG
PRINT_IF_DEBUGGING("test"); // -> debugPrint("test");
#undef DEBUG
PRINT_IF_DEBUGGING("test"); // -> print("test");
3. Caveats
One small caveat with this is that if DEBUG is defined it must expand to a valid preprocessing token (so it must only contain letters, digits and underscores) - otherwise the concatenation will result in an error.
So this would not work:
#define DEBUG ()
#define DEBUG +

macro definition containing #pragma

I am trying to define the following macro:
#if defined(_MSC_VER)
#define PRAGMA_PACK_PUSH(n) __pragma(pack(push, n))
#define PRAGMA_PACK_POP() __pragma(pack(pop))
#else
#define PRAGMA_PACK_PUSH(n) #pragma (pack(push, n))
#define PRAGMA_PACK_POP() #pragma (pack(pop))
#endif
But i get the following error on Linux -
error: '#' is not followed by a macro parameter
#define PRAGMA_PACK_PUSH(n) #pragma (pack(push, n))
and it points to the first ')' in the statment
How can i define a macro that contains a #?
Solution Update:
As stated in this thread Pragma in define macro the syntax that worked is:
#if defined(_MSC_VER)
#define PRAGMA_PACK_PUSH(n) __pragma(pack(push, n))
#define PRAGMA_PACK_POP() __pragma(pack(pop))
#else
#define PRAGMA_PACK_PUSH(n) _Pragma("pack(push, n)")
#define PRAGMA_PACK_POP() _Pragma("pack(pop)")
#endif
How can i define a macro that contains a #?
You can't (define a macro that contains a directive, that is. # can still be used in macros for stringization and as ## for token concatenation). That's why _Pragma was invented and standardized in C99. As for C++, it's definitely in the C++11 standard and presumably the later ones.
You can use it as follows:
#define PRAGMA(X) _Pragma(#X)
#define PRAGMA_PACK_PUSH(n) PRAGMA(pack(push,n))
#define PRAGMA_PACK_POP() PRAGMA(pack(pop))
With that,
PRAGMA_PACK_PUSH(1)
struct x{
int i;
double d;
};
PRAGMA_PACK_POP()
preprocesses to
# 10 "pack.c"
#pragma pack(push,1)
# 10 "pack.c"
struct x{
int i;
double d;
};
# 15 "pack.c"
#pragma pack(pop)
# 15 "pack.c"
As you can see, the _Pragmas are expanding to #pragma directives.
Since _Pragma is standard, you should be able to avoid the #ifdef here if Microsoft supports it.

#error inside of #define - Possible in C++ (generate error WHEN calling macro MyMacro IF some constant is not defined)?

I want to define the macro, that based on some condition (existence of #define INITED, not the parameter of the macro) will return value, or generate compiler's error, like:
#error Not initialized!
I've tried (for myIdea.h):
#ifdef INITED
#define MyMacro(x) x->method(); //something with x
#else
#define MyMacro(x) #error Not initalized!
#endif
But that code generates error (not the one I wanted to) expected macro format parameter.
Note, that I don't want that code (working, but doing bit different thing):
#ifdef INITED
#define MyMacro(x) x->method(); //something with x
#else
#error Not initalized!
#endif
The code above will geneate error just when INITED won't be defined. I want to generate error only when I call to the MyMacro() AND INITED has not been yet defined.
I'm not the slave to the first code, but I want the result to work exactly the way I've described above (generate error WHEN calling macro MyMacro IF constant inited is not defined).
This is not possible. The preprocessor is just a very simple thing, it does not parse nested macros like that. The second pound (#) would not be understood as a nested macro by the preprocessor. The argument is pretty much handled as raw string.
You could however look into static assert with C++11 and on instead of your #error directive. You would be writing then something like this:
#ifdef INITED
#define MyMacro(x) x->method(); //something with x
#else
#define MyMacro(x) static_assert(false, "Not initalized!");
#endif

Macro increase value and then concatenate

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

How do I turn a macro into a string using cpp?

GNU's cpp allows you to turn macro parameters into strings like so
#define STR(x) #x
Then, STR(hi) is substituted with "hi"
But how do you turn a macro (not a macro parameter) into a string?
Say I have a macro CONSTANT with some value e.g.
#define CONSTANT 42
This doesn't work: STR(CONSTANT). This yields "CONSTANT" which is not what we want.
The trick is to define a new macro which calls STR.
#define STR(str) #str
#define STRING(str) STR(str)
Then STRING(CONSTANT) yields "42" as desired.
You need double indirection magic:
#define QUOTE(x) #x
#define STR(x) QUOTE(x)
#define CONSTANT 42
const char * str = STR(CONSTANT);