UPDATE: Obviously, you’d want to do this using templates or a base class rather than macros. Unfortunately for various reasons I can’t use templates, or a base class.
At the moment I am using a macro to define a bunch of fields and methods on various classes, like this:
class Example { // Use FIELDS_AND_METHODS macro to define some methods and fields FIELDS_AND_METHODS(Example) };
FIELDS_AND_METHODS is a multi-line macro that uses stringizing and token-pasting operators.
I would like to replace this with the following kind of thing
class Example { // Include FieldsNMethods.h, with TYPE_NAME preprocessor symbol // defined, to achieve the same result as the macro. #define TYPE_NAME Example #include 'FieldsNMethods.h' };
Here I #define the name of the class (previously the parameter to the macro), and the FieldsNMethods.h file contains the content of the original macro. However, because I’m #including I can step into the code at runtime, when debugging.
However I am having trouble ‘stringizing’ and ‘token pasting’ the TYPE_NAME preprocessor symbol in the FieldsNMethods.h file.
For example, I want to define the destructor of the class in FieldsNMethods.h, so this would need to use the value of TYPE_NAME as below:
~TYPE_NAME() { //... }
But with TYPE_NAME replaced by its value.
Is what I’m attempting possible? I can’t use the stringizing and token-pasting operators directly, because I’m not in a macro definition.
This cries out for a template.
The direct answer to the last part of your question – ‘given that I’m not in a macro definition any more, how do I get pasting and stringizing operators to work’ – is ‘You can’t’. Those operators only work in macros, so you’d have to write macro invocations in order to get them to work.
Added:
@mackenir said ‘templates are not an option’. Why are templates not an option? The code is simulating templates the old-fashioned pre-standard, pre-template way, and does so causing much pain and grief. Using templates would avoid that pain — though there’d be a conversion operation.
@mackenir asked ‘is there a way to make things work with macros?’ Yes, you can, but you should use templates – they are more reliable and maintainable. To make it work with macros, then you’d have to have the function names in the code in the included header be macro invocations. You need to go through a level of indirection to get this to work correctly:
This level of indirection is an often necessary idiom for both tokenizing and stringizing operators.
Additional comments from @mackenir indicate continued problems. Let’s make it concrete.
OK. To make this concrete, we need a
FIELDS_AND_METHODS(type)macro that is multi-line and uses token-pasting (I’m not going to deal with stringizing – the same basic mechanisms will apply, though).With luck, this declares a member of the type ‘pointer to argument type’, a constructor for that type, and a method (Example_next in this case) that returns that pointer.
So, this might be the macro – and we need to replace it such that the ‘#include’ does the equivalent job.
The content of fieldsNmethods.h becomes:
Note that the header would not contain multiple-inclusion guards; its raison d’etre is to allow it to be included multiple times. It also undefines its helper macros to permit multiple inclusion (well, since the redefinitions would be identical, they’re ‘benign’ and wouldn’t cause an error), and I prefixed them with
FNM_as a primitive namespace control on the macros. This generates the code I’d expect from the C pre-processor. and G++ doesn’t witter but produces an empty object file (because the types declared are not used in my example code).Note that this does not require any changes to the calling code except the one outlined in the question. I think the question should be improved using the SPOT ‘Single Point of Truth’ principle (or DRY ‘Don’t Repeat Yourself’):