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 +
Related
I have the following problem:
#define CONCAT_(A,B) A ## B
#define CONCAT(A,B) CONCAT_(A,B)
#define CREATE_NAME(N) CONCAT(N, __COUNTER__)
If I wanted to retrieve a specific variable##__COUNTER__ later in the code how can I achieve this? I only need to get the previous one, something like:
#define CONCAT_(A,B) A ## B
#define CONCAT(A,B) CONCAT_(A,B)
#define CREATE_NAME(N) CONCAT(N, __COUNTER__)
#define GET_NAME_PREV(N, VAL) CONCAT(N, VAL)
auto CREATE_NAME(v);
auto test_current_counter_value = GET_NAME_PREV(v, __COUNTER__ -1);
Thank you.
BOOST_PP_SUB macro from boost library can be evaluated and expanded to an identifier.
#include <boost/preprocessor/arithmetic/sub.hpp>
#define CONCAT_(A,B) A ## B
#define CONCAT(A,B) CONCAT_(A,B)
#define CREATE_NAME(N) CONCAT(N, __COUNTER__)
#define GET_NAME_PREV(N) CONCAT(N, BOOST_PP_SUB(__COUNTER__, 1))
auto CREATE_NAME(v) = true;
auto test_current_counter_value = GET_NAME_PREV(v);
Try it on Compiler Explorer.
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.
In my project I have very many files and I want to manage debug with C++ macros. For every file, I want to use its own switch for enable or disable debug and adjust debug level. So basically there is shared file with settings:
This is how shared file debug.h looks:
#define DEBUG_LEVEL_LOG -1
#define DEBUG_LEVEL_NONE 0
#define DEBUG_LEVEL_ERROR 1
#define DEBUG_LEVEL_WARNING 2
#define DEBUG_LEVEL_INFO 3
#define DEBUG_LEVEL_DEBUG 4
#define DEBUG_LEVEL_TRACE 5
#ifndef ON
#define ON 1
#endif
#ifndef OFF
#define OFF 0
#endif
// setings for component "wireless"
#define WIRELESS_DEBUGGING ON
#define WIRELESS_DEBUGGING_LEVEL DEBUG_LEVEL_ERROR
// settings for another components
...
In every file I want to debug with this settings I need to define another bunch of macros. For example file "wireless.h"
#ifndef WIRELESS_DEBUGGING
#define WIRELESS_DEBUGGING_LEVEL DEBUG_LEVEL_NONE
#endif
#if WIRELESS_DEBUGGING
#if WIRELESS_DEBUGGING_LEVEL >= DEBUG_LEVEL_LOG
#define WIRELESS_LOG(...); Logger::log(__VA_ARGS__);
#else
#define WIRELESS_LOG(...); {}
#endif
#if WIRELESS_DEBUGGING_LEVEL >= DEBUG_LEVEL_ERROR
#define WIRELESS_ERROR(...); Logger::error(__VA_ARGS__);
#else
#define WIRELESS_ERROR(...); {}
#endif
#if WIRELESS_DEBUGGING_LEVEL >= DEBUG_LEVEL_WARNING
#define WIRELESS_WARNING(...); Logger::warning(__VA_ARGS__);
#else
#define WIRELESS_WARNING(...); {}
#endif
#if WIRELESS_DEBUGGING_LEVEL >= DEBUG_LEVEL_INFO
#define WIRELESS_INFO(...); Logger::info(__VA_ARGS__);
#else
#define WIRELESS_INFO(...); {}
#endif
#if WIRELESS_DEBUGGING_LEVEL >= DEBUG_LEVEL_DEBUG
#define WIRELESS_DEBUG(...); Logger::debug(__VA_ARGS__);
#else
#define WIRELESS_DEBUG(...); {}
#endif
#if WIRELESS_DEBUGGING_LEVEL >= DEBUG_LEVEL_TRACE
#define WIRELESS_TRACE(...); Logger::trace(__VA_ARGS__);
#else
#define WIRELESS_TRACE(...); {}
#endif
#else
#define WIRELESS_LOG(...); {}
#define WIRELESS_ERROR(...); {}
#define WIRELESS_WARNING(...); {}
#define WIRELESS_INFO(...); {}
#define WIRELESS_DEBUG(...); {}
#define WIRELESS_TRACE(...); {}
#endif
When I want to debug given component, I simply use something like this (in wireless.cpp)
WIRELESS_TRACE("wireless: hello world\n");
... etc ...
So far it's working. And here is the question: I don't want to use "local" bunch of definitions similar to definitions in file "wireless.h" in every component I'm using only with different prefix. Instead of this I want to have some "super macro" which will look similar to this
REGISTER_DEBUG(WIRELESS);
Is there a way how to achieve this using some concatenation and multi-line macro? I have found that using #define inside #define is forbidden.
I'm not completely sure what you want, so if this doesn't fit let me know and I'll delete.
There is the possibility of concatenating tokens in the preprocessor using ##. See, for example, https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html
This is somewhat clumsy, but should do the trick:
#define DEBUG_LEVEL_LOG -1
#define DEBUG_LEVEL_NONE 0
#define DEBUG_LEVEL_ERROR 1
#define DEBUG_LEVEL_WARNING 2
#define DEBUG_LEVEL_INFO 3
#define DEBUG_LEVEL_DEBUG 4
#define DEBUG_LEVEL_TRACE 5
#define TRACE(a,...) _TRACE(a,__VA_ARGS__)
#define _TRACE(a,...) __TRACE_##a(__VA_ARGS__)
#define __TRACE_5(...) do{Logger::trace(__VA_ARGS__);}while(0)
Here is the clumsiness: you also need to define __TRACE_4, __TRACE_3 and so on to be empty. And then you need to define the same thing for Debug:
#define __DEBUG_4(...) do{Logger::debug(__VA_ARGS__);}while(0)
But in the end, after you defined your Wireless log level:
#define WIRELESS_LEVEL 5
you can just call the macro just like this:
TRACE(WIRELESS_LEVEL,"wireless: hello world\n");
Edit
Alternatively (this might be cleaner):
#define __PRINT_55(...) do{Logger::trace(__VA_ARGS__);}while(0)
#define __PRINT_44(...) do{Logger::debug(__VA_ARGS__);}while(0)
// etc...
// Also need to define what you need to be not printed:
#define __PRINT_01(...)
// etc...
#define PRINT(a,b,...) _PRINT(a,b,__VA_ARGS__)
#define _PRINT(a,b,...) __PRINT_##a##b(__VA_ARGS__)
Now you can call your function like this:
PRINT(DEBUG_LEVEL_TRACE, WIRELESS_LEVEL, "Hello world\n");
You can get there by switching from macros to inline functions. Something like this:
// debug.h
enum DebugLevel {
DEBUG_LEVEL_LOG = -1,
DEBUG_LEVEL_NONE = 0,
DEBUG_LEVEL_ERROR = 1,
DEBUG_LEVEL_WARNING = 2,
DEBUG_LEVEL_INFO = 3,
DEBUG_LEVEL_DEBUG = 4,
DEBUG_LEVEL_TRACE = 5
};
// settings for component "wireless"
constexpr bool WIRELESS_DEBUGGING = true;
constexpr DebugLevel WIRELESS_DEBUGGING_LEVEL = DEBUG_LEVEL_ERROR;
#define REGISTER_DEBUG_FUNC(topic, level, func) \
template <typename... Args> \
inline void topic##_##level(Args&& ... args) { \
if ( topic##_DEBUGGING && topic##_DEBUGGING_LEVEL >= DEBUG_LEVEL_##level ) \
Logger::func(std::forward<Args>(args)...); \
}
#define REGISTER_DEBUG(topic) \
REGISTER_DEBUG_FUNC(topic, LOG, log) \
REGISTER_DEBUG_FUNC(topic, ERROR, error) \
REGISTER_DEBUG_FUNC(topic, WARNING, warning) \
REGISTER_DEBUG_FUNC(topic, INFO, info) \
REGISTER_DEBUG_FUNC(topic, DEBUG, debug) \
REGISTER_DEBUG_FUNC(topic, TRACE, trace)
// wireless.h
REGISTER_DEBUG(WIRELESS)
Trying to get this working in VS2013 (see Variadic macro trick and C++ preprocessor __VA_ARGS__ number of arguments).
It's not a duplicate afaik (versions posted elsewhere only work with GCC).
Any ideas what's wrong with this? I'm almost there...
#define _EXPAND(x) x
#define _VA_NARGS_IMPL(_1_, _2_, _3_, _4_, _5_, N, ...) N
#define _VA_NARGS_IMPL2(...) _EXPAND(_VA_NARGS_IMPL(__VA_ARGS__, 4, 3, 2, 1, 0))
#define _PUSH_X_FRONT(...) X, __VA_ARGS__
/*
Returns the number of arguments specified.
#ifndef _MSC_VER
#define VA_NARGS(...) _VA_NARGS_IMPL2(X,##__VA_ARGS__)
*/
#define VA_NARGS(...) _VA_NARGS_IMPL2(_PUSH_X_FRONT(__VA_ARGS__))
// testing is gewd
static_assert(VA_NARGS() == 0, "VA_NARGS() failed for 0 arguments");
static_assert(VA_NARGS(one, two, three, four) == 4, "VA_NARGS() failed for 4 arguments");
#define _VARARG_IMPL2(N, Macro, ...) Macro##N(__VA_ARGS__)
#define _VARARG_IMPL(N, Macro, ...) _VARARG_IMPL2(N, Macro, __VA_ARGS__)
// Helper function for variadic macros with per-argument processing.
#define VARARG(Macro, ...) _VARARG_IMPL(VA_NARGS(__VA_ARGS__), Macro, __VA_ARGS__)
#define _Quote1(x) #x
#define _Quote2(x, ...) #x, _Quote1(__VA_ARGS__)
#define _Quote3(x, ...) #x, _Quote2(__VA_ARGS__)
#define _Quote4(x, ...) #x, _Quote3(__VA_ARGS__)
// Treat each argument as a string literal, encompassing in quotes.
#define Quote(...) VARARG(_Quote, __VA_ARGS__)
Question:
constexpr char *a[] = { Quote(a, b) };
// WHY does the above produce {"a, b"} with msvc?
// The following produces {"a", "b"} as expected
constexpr char *a[] = { _Quote2(s, c) };
It is difficult to make a real variadic macro to work in VS2013. I had something done to expand a macro to be interpreted on it's own as a new macro. The key is to make multiple level macros. It is a lot to code but for given sample it will work.
#define InitialMacro (argument1, argument2) \
DetailedMacro(argument1, argument2, argument1##_description, argument2##_description)
#define DetailedMacro (argument1, argument2, argument3, argument4) \
L#argument1 \
L#argument2 \
L#argument3 \
L#argument4
The ideea presented here is to implement enough macros to cover all your requirement in the number of parameters nedeed. Also you can forward/update macro with aditional items on the way.
Basically first macro in this example append to the second and third transmitted parameters the suffix _description resulting in another macro that will get interpreted as a macro and it will be expanded in DetailedMacro.
You could also take a look at this: msvc variadic macro expansion
I know C++ template metaprogramming is Turing-complete. Does the same thing hold for preprocessor metaprogramming?
Well macros don't directly expand recursively, but there are ways we can work around this.
The easiest way of doing recursion in the preprocessor is to use a deferred expression. A deferred expression is an expression that requires more scans to fully expand:
#define EMPTY()
#define DEFER(id) id EMPTY()
#define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)()
#define EXPAND(...) __VA_ARGS__
#define A() 123
A() // Expands to 123
DEFER(A)() // Expands to A () because it requires one more scan to fully expand
EXPAND(DEFER(A)()) // Expands to 123, because the EXPAND macro forces another scan
Why is this important? Well when a macro is scanned and expanding, it creates a disabling context. This disabling context will cause a token, that refers to the currently expanding macro, to be painted blue. Thus, once its painted blue, the macro will no longer expand. This is why macros don't expand recursively. However, a disabling context only exists during one scan, so by deferring an expansion we can prevent our macros from becoming painted blue. We will just need to apply more scans to the expression. We can do that using this EVAL macro:
#define EVAL(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
#define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
#define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
#define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
#define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__)))
#define EVAL5(...) __VA_ARGS__
Now if we want to implement a REPEAT macro using recursion, first we need some increment and decrement operators to handle state:
#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
#define INC(x) PRIMITIVE_CAT(INC_, x)
#define INC_0 1
#define INC_1 2
#define INC_2 3
#define INC_3 4
#define INC_4 5
#define INC_5 6
#define INC_6 7
#define INC_7 8
#define INC_8 9
#define INC_9 9
#define DEC(x) PRIMITIVE_CAT(DEC_, x)
#define DEC_0 0
#define DEC_1 0
#define DEC_2 1
#define DEC_3 2
#define DEC_4 3
#define DEC_5 4
#define DEC_6 5
#define DEC_7 6
#define DEC_8 7
#define DEC_9 8
Next we need a few more macros to do logic:
#define CHECK_N(x, n, ...) n
#define CHECK(...) CHECK_N(__VA_ARGS__, 0,)
#define NOT(x) CHECK(PRIMITIVE_CAT(NOT_, x))
#define NOT_0 ~, 1,
#define COMPL(b) PRIMITIVE_CAT(COMPL_, b)
#define COMPL_0 1
#define COMPL_1 0
#define BOOL(x) COMPL(NOT(x))
#define IIF(c) PRIMITIVE_CAT(IIF_, c)
#define IIF_0(t, ...) __VA_ARGS__
#define IIF_1(t, ...) t
#define IF(c) IIF(BOOL(c))
#define EAT(...)
#define EXPAND(...) __VA_ARGS__
#define WHEN(c) IF(c)(EXPAND, EAT)
Now with all these macros we can write a recursive REPEAT macro. We use a REPEAT_INDIRECT macro to refer back to itself recursively. This prevents the macro from being painted blue, since it will expand on a different scan(and using a different disabling context). We use OBSTRUCT here, which will defer the expansion twice. This is necessary because the conditional WHEN applies one scan already.
#define REPEAT(count, macro, ...) \
WHEN(count) \
( \
OBSTRUCT(REPEAT_INDIRECT) () \
( \
DEC(count), macro, __VA_ARGS__ \
) \
OBSTRUCT(macro) \
( \
DEC(count), __VA_ARGS__ \
) \
)
#define REPEAT_INDIRECT() REPEAT
//An example of using this macro
#define M(i, _) i
EVAL(REPEAT(8, M, ~)) // 0 1 2 3 4 5 6 7
Now this example is limited to 10 repeats, because of limitations of the counter. Just like a repeat counter in a computer would be limited by the finite memory. Multiple repeat counters could be combined together to workaround this limitation, just like in a computer. Furthermore, we could define a FOREVER macro:
#define FOREVER() \
? \
DEFER(FOREVER_INDIRECT) () ()
#define FOREVER_INDIRECT() FOREVER
// Outputs question marks forever
EVAL(FOREVER())
This will try to output ? forever, but will eventually stop because there are no more scans being applied. Now the question is, if we gave it an infinite number of scans would this algorithm complete? This is known as the halting problem, and Turing completeness is necessary to prove the undecidability of the halting problem. So as you can see, the preprocessor can act as a Turing complete language, but instead of being limited to the finite memory of a computer it is instead limited by the finite number of scans applied.
No. The C++ preprocessor does not allow for unlimited state. You only have a finite number of on/off states, plus a include stack. This makes it a push-down automaton, not a turing machine (this ignores also the fact that preprocessor recursion is limited - but so is template recursion).
However, if you bend your definitions a bit, this is possible by invoking the preprocessor multiple times - by allowing the preprocessor to generate a program which re-invokes the preprocessor, and looping externally, it is indeed possible to make a turing machine with the preprocessor. The linked example uses C, but it should be adaptable into C++ easily enough.