How to Temporarily Disable a MACro Expansion in C/C++

How do I temporarily disable a macro expansion in C/C++?

In MSVC you could use push_macro pragma, GCC supports it for compatibility with Microsoft Windows compilers.

#pragma push_macro("MACRONAME")
#undef MACRONAME

// some actions

#pragma pop_macro("MACRONAME")

How to disable macros imported from C-Header

You already know about the #undef option, which would do what you need.

There is another option however. You could completely hide the fact that your A uses library C from your users: Define your own types and interface in the header and class definition of A and remove the library include from your A header. Then in your implementation file you can include the library header and utilize the library in whatever manner is needed, all the while hiding the include of the c_library.h from your users. This has the added advantage of reducing the coupling between your class users, your class, and the library that it depends on.

How to disable macro function?

The idea is for the macro to do nothing on release builds. You could define it to an empty string literal, since ""; is a valid expression. I would believe the reason of being defined to ((void)0) is so that the implementation does not emmit warnings for the expression. I have no solid grounds to say this, but some minimal testing shows that ""; generates a warning while ((void)0) doesn't. Of course, warnings are not standarized so there could be a particular implementation that does emit a warning for ((void)0) as well, but it would have to define assert to something else that doesn't on NDEBUG builds or it would be quite annoying to the user.

Temporarily overwrite a macro in C preprocessor

As already said, it is not really possible. Depending on the situation, this might be a workaround:

#include "generalmacrodefs.h" // put them in here or include them indirectly
#undef macro1
#define macro1 "specialized temporary value"
#undef macro1
#include "generalmacrodefs.h" // restores

This requires that generalmacrodefs.h uses a pattern like this at least for the definitions you might temporarily overwrite:

#ifndef macro1
#define macro1 "original value"
#endif

CPP: avoiding macro expansion of a macro function parameter

I'm doing:

#include <cstdio>

#define FOO 1
#define BAR 2

#define LOG_SIMPLE(ptr, lib, str) printf("%s\n", #lib);
#define LOG(ptr, lib, str) LOG_SIMPLE(ptr, ##lib, str)

int main()
{
LOG_SIMPLE(0, FOO, "some error");
LOG(0, BAR, "some other error");
}

which prints out:

FOO
BAR

Works with MSVC2005 but not with gcc/g++.


EDIT: to make it work with gcc/g++ you can abuse variadic macros:

#include <stdio.h>

#define FOO 1
#define BAR 2

#define LOG_SIMPLE(ptr, str, lib) printf("%s\n", #lib);
#define LOG(ptr, str, lib, ...) LOG_SIMPLE(ptr, str, lib##__VA_ARGS__)

int main()
{
LOG_SIMPLE(0, "some error", FOO);
LOG(0, "some other error", BAR);
LOG(0, "some other error", FOO, BAR);
}

However, it's your discipline not to use the macro with too many parameters. MSVC2005 prints out

FOO
BAR
FOO2

while gcc prints out

FOO
BAR
FOOBAR

C++ Stop Preprocessor Macro Expansion

What you're trying to do is not possible, as Michael Karcher's answer states: #define delete already makes the program ill-formed, and expanding an object-like macro (outside its own expansion) cannot be avoided.

However, for your particular use case detailed in the question, a workaround is possible. You could put your #define delete into a header file (let's call it debug_delete.hxx), like this:

#ifdef delete
# undef delete
#endif
#define delete MyCustomDelete(__FILE__, __LINE__), delete

Then, create another header file (let's call it normal_delete.hxx):

#ifdef delete
# undef delete
#endif

Note in particular that there is no mechanism in these headers to prevent multiple inclusion; in fact, we want them includable an arbitrary number of times.

Then, wrap code which must use = delete; in appropriate #include directives:

class A {
#include "normal_delete.hxx"
A() = delete;
#include "debug_delete.hxx"
~A() { delete p; }
};

(Yes, it's ugly, but what you're doing is sort of ugly in the first place, so ugly code may be required to make it work).

How to disable a warning within a C++ macro

In your case you have to use the extension __pragma

__pragma

instead of

#pragma

Suppress C Macro Variable Substitution

You can define a different macro to expand to name, like this:

#define Name name

and change the name field in the PRIMITIVE macro to use the new macro, like this:

#define PRIMITIVE(name) \
do \
{ \
VocabEntry* entry = (VocabEntry*)gc_alloc(sizeof(VocabEntry)); \
entry->code = name; \
entry->Name = cstr_to_pstr(#name); \
entry->prev = latest_vocab_entry; \
latest_vocab_entry = entry; \
} \
while (false)

Other than using something different from the parameter name in the macro body or changing the parameter name, there is no other way to do this in the C language. Per C 2011 (N1570) 6.10.3.1 1, when a function-like macro is recognized, parameter names are immediately substituted except when # or ## is present, and there no other exceptions:

After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded.

The # token changes the parameter name to a string, which is no use in this situation. The ## token expands the parameter name and pastes it together with an adjacent token, which is also no use in this situation.



Related Topics



Leave a reply



Submit