Here is my example code https://godbolt.org/z/VKgKik
#define delete MyCustomDelete(__FILE__, __LINE__), delete
#define CAT(X,Y) CAT2(X,Y)
#define CAT2(X,Y) X##Y
#define CAT_3(X,Y,Z) CAT(X,CAT(Y,Z))
class A {
A() = CAT_3(de,le,te);
};
The godbolt example is setup to display the preprocessor output. The goal is that at the end of the preprocessor pass i want the output code to be
class A {
A() = delete;
};
currently "ThisShouldNotshowUp" is displayed there instead. I thought the use of the ## operator would stop the preprocessor from reexpanding but it did not.
I realize removing the "#define delete" would solve the problem but I need this define there. The reason I have created a macro with the same name as delete is because I want to be able to track the news and deletes, and If a memory leak occurs I can see what line of code aloced it. This macro thus means I can continue to use the keyword delete in my code and the File and line numbers get filled in for free. As far as i know there is no other way to achieve this functionailty except by defined a delete macro. This is the crux of the problem. The delete macro has given me a powerful debug tool however it has removed a useful language feature for me to use.
Macro expansion overviewThe preprocessor maintains a context stack, implemented as a linked list of cpp_context structures, which together represent the macro expansion state at any one time. The struct cpp_reader member variable context points to the current top of this stack.
This is called token pasting or token concatenation. The ' ## ' preprocessing operator performs token pasting.
All preprocessor directives are interpreted before macro expansion begins, so no, you cannot have a macro expand into an #include directive and have it be interpreted as such. Instead, it will be interpreted as (erroneous) C++ code.
The double-number-sign or token-pasting operator (##), which is sometimes called the merging or combining operator, is used in both object-like and function-like macros. It permits separate tokens to be joined into a single token, and therefore, can't be the first or last token in the macro definition.
You have no chance in creating a preprocessing token that is the name of an object-like macro from expanding a macro. The relevant section of n3337 is [cpp.rescan]
. I quote a shortened part of the first paragraph in it.
After all parameters in the replacement list have been substituted and
#
and##
processing has taken place [...]. Then the resulting preprocessing token sequence is rescanned [...] for more macro names to replace.
Nonwithstanding the problem, that delete
is technically forbidden to be a macro name, there is no way to prevent the macro name to be recognized while rescanning.
You probably mixed up the fact that ##
operator does use it's parameters without expansion with the idea that the result of ##
doesn't undergo 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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With