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