jackhab
jackhab

Reputation: 17698

How to redefine a macro using its previous definition

Suppose I have the following macro:

#define xxx(x) printf("%s\n",x);

Now in certain files I want to use an "enhanced" version of this macro without changing its name. The new version explores the functionality of the original version and does some more work.

#define xxx(x) do { xxx(x); yyy(x); } while(0)

This of course gives me redefition warning but why I get 'xxx' was not declared in this scope? How should I define it properly?

EDIT: according to this http://gcc.gnu.org/onlinedocs/gcc-3.3.6/cpp/Self_002dReferential-Macros.html it should be possible

Upvotes: 14

Views: 11503

Answers (7)

Ivan Lazaric
Ivan Lazaric

Reputation: 43

This answer doesn't answer your question exactly, but I feel like it does a good job at working the way you would intend to use your method (if it was possible).
The idea is for all of your file-specific macros that do actual work to have a unique name (for example LOG_GENERIC and LOG_SPECIFIC), and having the common token (in your case xxx) simply point to the currently appropriate macro.
Plus, using non-standard but widely available #pragma push_macro and #pragma pop_macro we can both modify the common xxx token and restore it to the previous version.
For example, imagine two header files, generic.hpp and specific.hpp, common token here being LOG:

// generic.hpp
#pragma once

#include <cstdio>

#define LOG_GENERIC(x) printf("INFO: " x "\n")
#define LOG LOG_GENERIC

void generic_fn(){LOG("generic");} // prints "INFO: generic\n"
// specific.hpp
#pragma once

#include "generic.hpp"

#define LOG_SPECIFIC(x) do {printf("<SPECIFIC> "); LOG_GENERIC(x);} while (0)

#pragma push_macro("LOG")
#undef LOG
#define LOG LOG_SPECIFIC

void specific_fn(){LOG("specific");} // prints "<SPECIFIC> INFO: specific\n"

#undef LOG
#pragma pop_macro("LOG")

By doing things this way we get the benefits of:

  • an easy mechanism to modify LOG in a restorable way via #pragma push_macro and #pragma pop_macro
  • being able to refer to certain LOG_* macros explicitly (LOG_SPECIFIC can use LOG_GENERIC)
    • we can't refer to LOG inside of LOG_SPECIFIC definition, we have to go through LOG_GENERIC
    • this is different to your question, but personally I am of the opinion that this is the better design, otherwise you gain the ability to allow macros above the LOG_SPECIFIC definition to affect it, just sounds like the wrong thing to do every time

Link to a github repository with the example above

Upvotes: 0

From: https://gcc.gnu.org/onlinedocs/gcc/Push_002fPop-Macro-Pragmas.html

#define X  1
#pragma push_macro("X")
#undef X
#define X -1
#pragma pop_macro("X")
int x [X];

Upvotes: 2

snv.dev
snv.dev

Reputation: 101

If we know type of 'x' parameter in the 'xxx' macro, we can redefine macro by using it in a function and then define the 'xxx' macro as this function

Original definition for the 'xxx' macro:

#define xxx(x) printf("xxx %s\n",x);

In a certain file make enhanced version of the 'xxx' macro:

/* before redefining the "xxx" macro use it in function 
 * that will have enhanced version for "xxx" 
 */
static inline void __body_xxx(const char *x)
{
    xxx(x);
    printf("enhanced version\n");
}

#undef  xxx
#define xxx(x) __body_xxx(x)

Upvotes: 3

Miquel Ramirez
Miquel Ramirez

Reputation: 543

Self-referential macros do not work at all:

http://gcc.gnu.org/onlinedocs/cpp/Self_002dReferential-Macros.html#Self_002dReferential-Macros

If you're working on C++ you can obtain the same results with template functions and namespaces:

template <typename T> void xxx( x ) {
        printf( "%s\n", x );
}

namespace my_namespace {

template <typename T> void xxx( T x ) {
        ::xxx(x);
        ::yyy(x);
}

}

Upvotes: 4

Mike
Mike

Reputation: 674

You won't be able to reuse the old definition of the macro, but you can undefine it and make the new definition. Hopefully it isn't too complicated to copy and paste.

#ifdef xxx
#undef xxx
#endif
#define xxx(x) printf("%s\n",x);

My recommendation is defining an xxx2 macro.

#define xxx2(x) do { xxx(x); yyy(x); } while(0);

Upvotes: 4

AProgrammer
AProgrammer

Reputation: 52284

Not possible. Macros can use other macros but they are using the definition available at expand time, not definition time. And macros in C and C++ can't be recursive, so the xxx in your new macro isn't expanded and is considered as a function.

Upvotes: 6

ereOn
ereOn

Reputation: 55736

It is not exactly what you're asking for but it can help.

You can #undef a macro prior to giving it a new definition.

Example:

#ifdef xxx
#undef xxx
#endif
#define xxx(x) whatever

I never heard of (or seen) a recursive macro though. I don't think it is possible.

Upvotes: 0

Related Questions