How to capture argument expression as string literal without using macro? - c++

In C, it is quite common to capture argument as string literl via macro as mentioned in this answer:
#define CALL_DO_SOMETHING(VAR) do_something(#VAR, VAR);
But on the other hand, there are many projects with policies against the usage of macro and recommend always using templates instead.
I am wondering if it is possible to express the similar syntax in a modern C++ way or it is yet another corner case where macro has to be used?

Stringification can only be done by MACRO.

Related

How to concatenate/join __VA_ARGS__ with delimiters/separators?

I would like to expand a variadic macro to another macro that takes a single argument, which is formed by joining the variadic arguments with a delimiter/separator (e.g. "_"). Something like this:
#define FOO(...)
FOO(a, b, c, d);
which expands into
#define BAR(X)
BAR(a_b_c_d);
I know there is __VA_ARGS__ for working with the variadic parameters, and ## for concatenation. How do I use them together to achieve what I want (preferably using C++17 and older language features, without libraries such as Boost)?
First, there are no language feature that directly tackles the question you are trying to solve. (there might be complier specific ones, but I don't know).
However, if you know the upper limit of the amount of argument that macro can take(preferably not too many), you can use this answer as a guide to iterate through the __VA_ARGS__: Is it possible to iterate over arguments in variadic macros?
On the other hand, Boost.Preprocessor is a header only library. While it is a pretty heavy macro-only library that could bring a lot of ugliness behind the scene, it does offer simple ways to handle macros that take up to thousands of parameter.
Here's a quick one that should work for you:
#define CAT_OP(index, state, elem) BOOST_PP_CAT(state, BOOST_PP_CAT(_, elem))
#define CAT_SEQ(seq) BOOST_PP_SEQ_FOLD_LEFT(CAT_OP, BOOST_PP_SEQ_HEAD(seq), BOOST_PP_SEQ_TAIL(seq))
#define CAT_VA_ARGS(...) CAT_SEQ(BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
Demo.
It treats the variadic as a Sequence, then performs a left fold over the sequence with concat operation.

Is it possible to have a function-like macro and an object-like macro over the same char sequence?

My problem is this - I tried to make a Heap checker to be used in testing and for this
a) overload standard global new/delete operators so that they let my custom class know about each alloc and delete
b) add custom new operators that have a signature like
void* operator new(size_t size, const char* filename, const char* function, int line)
c) make a macro that replaces standard new calls with my new calls and the given file, func & line
#define new new(__FILE__, __FUNCTION__, __LINE__)
this works well, except for cases where somebody uses a custom new in a class or operator new() directly - that means that I can only define this macro after loading in standard C++ libs (functional, algo, string...), as they are heavy on doing that stuff
d) so we came up with the brilliant idea of using var-arg macro which would solve these problems
#define new(...) new(__VA_ARGS__, __FILE__, __FUNCTION__, __LINE__)
this works well for all the problematic cases in the last point, as any parameters passed to either new (someargs) or operator new(size_t, someargs) gets replaced by the var-arg macro and sent into my custom new operators
But it doesn't work for the most usual case of just calling:
int* ptr = new int;
because the new call doesn't have parentheses, therefore it's not expanded as a function macro
Which brings me to the question mentioned in the title :
Is there any way to do this with macros so that one would be able to replace the same character sequence in original code no matter whether it's called without a parameter list or with one?
The desired result in this case would be:
new without parentheses after it - new -> new(__file__, __func__, __line__)
new with parentheses after it - new(args) -> new(args, __file__, __func__, __line__)
I realize that this is an obvious case of trying to redefine the same macro, so it shouldn't be possible. I'm looking for some preprocessor magic that would let me get around that.
Disclaimer : I know it's ugly and we actually settled on the solution in c) with simply ignoring the standard library news. But as I did spend some time researching the possibility I'd be interested if anyone has a potential way to do this.
Cheerios!
___EDIT___
Please don't concentrate on what I'm trying to accomplish but only on the question in the title. The Heap Checker itself can be implemented in a variety of standard-compliant ways and this is not one of them :) It's more of my curiosity as to how much it's possible to bend the language with the preprocessor.
The question stands - can I use some preprocessor commands to achieve a different behaviour for the same sequence with and without parentheses after it (that is, something that works just as if I had both a function-like and object-like macro of the same name)
Thanks for any and all answers :)
No, you can't. See ยง16.3p2 [cpp.replace] of the C++ standard (similar wording found in other versions and in the equivalent section of the C standard; nothing has changed) (emphasis mine):
An identifier currently defined as an object-like macro (see below) may be redefined by another #define preprocessing directive provided that the second definition is an object-like macro definition and the two
replacement lists are identical, otherwise the program is ill-formed. Likewise, an identifier currently defined as a function-like macro (see below) may be redefined by another #define preprocessing directive provided that the second definition is a function-like macro definition that has the same number and spelling of parameters, and the two replacement lists are identical, otherwise the program is ill-formed.
In other words, a macro identifier is either object-like or function-like, but the same identifier cannot be used for both.

C++ Macro's Token-Paster as argument of a function

I was searching for a while on the net and unfortunately i didn't find an answer or a solution for my problem, in fact, let's say i have 2 functions named like this :
1) function1a(some_args)
2) function2b(some_args)
what i want to do is to write a macro that can recognize those functions when feeded with the correct parameter, just that the thing is, this parameter should be also a parameter of a C/C++ function, here is what i did so far.
#define FUNCTION_RECOGNIZER(TOKEN) function##TOKEN()
void function1a()
{
}
void function2a()
{
}
void anotherParentFunction(const char* type)
{
FUNCTION_RECOGNIZER(type);
}
clearly, the macro is recognizing "functiontype" and ignoring the argument of anotherParentFunction, i'm asking if there is/exist a trick or anything to perform this way of pasting.
thank you in advance :)
If you insist on using a macro: Skip the anotherParentFunction() function and use the macro directly instead. When called with constant strings, i.e.
FUNCTION_RECOGNIZER( "1a");
it should work.
A more C++ like solution would be to e.g use an enum, then implement anotherParentFunction() with the enum as parameter and a switch that calls the corresponding function. Of course you need to change the enum and the switch statement then every time you add a new function, but you would be more flexible in choosing the names of the functions.
There are many more solutions to achieve something similar, the question really is: What is your use case? What do want to achieve?
In 16.1.5 the standard says:
The implementation can process and skip sections of source files conditionally, include other source files, and replace macros. These capabilities are called preprocessing, because conceptually they occur before translation of the resulting translation unit.
[emphasis mine]
Originally pre-processing was done by a separate app, it is essentially an independent language.
Today, the pre-processor is often part of the compiler, but - for example - you can't see macros etc in the Clang AST tree.
The significance of this is that the pre-processor knows nothing about types or functions or arguments.
Your function definition
void anotherParentFunction(const char* type)
means nothing to the pre-processor and is completely ignored by it.
FUNCTION_RECOGNIZER(type);
this is recognized as a defined macro, but type is not a recognized pre-processor symbol so it is treated as a literal, the pre-processor does not consult the C++ parser or interact with it's AST tree.
It consults the macro definition:
#define FUNCTION_RECOGNIZER(TOKEN) function##TOKEN()
The argument, literal type, is tokenized as TOKEN. The word function is taken as a literal and copied to the result string, the ## tells the processor to copy the value of the token TOKEN literally, production functiontype in the result string. Because TOKEN isn't recognized as a macro, the ()s end the token and the () is appended as a literal to the result string.
Thus, the pre-processor substitutes
FUNCTION_RECOGNIZER(type);
with
functiontype();
So the bad news is, no there is no way to do what you were trying to do, but this may be an XY Problem and perhaps there's a solution to what you were trying to achieve instead.
For instance, it is possible to overload functions based on argument type, or to specialize template functions based on parameters, or you can create a lookup table based on parameter values.

Rationale on Boost.Preprocessor using macros instead of simple defines?

For example BOOST_PP_ITERATE and BOOST_PP_ITERATION, as seen on GMan's answere here, are preprocessor macros, without any parameters. Is there a reason they're not just simple defines and used as such without ()?
Generally, function like macro can be used to prevent unintentional macro
expansion.
For example, assuming that we have the following macro call:
BOOST_PP_CAT( BOOST_PP_ITERATION, _DEPTH )
and we expect this will be expanded into BOOST_PP_ITERATION_DEPTH.
However, if BOOST_PP_ITERATION is an object like(non-functional) macro,
it will be expanded to its own definition before the token
BOOST_PP_ITERATION_DEPTH is generated by concatenation.
Presumably because they perform operations: consequently, their usage should make it clear that you are actually invoking something and not just using some constant.

Is there a way to make C macros keyword agnostic?

Is there a way to concatenate keywords in a macro and get
C to behave in a more dynamic fashion as in:
#define macro(fun,ction,var,iable) function(variable)
I know this kind of thing exists in other languages.
You can use ## to concatinate names in macros
fun##ction ...
No. Although there is ## as Michael says, it is applied (as all preprocessing) before C or C++ looks at keywords, and even using it to generate any preprocessing keyword is allowed to crash the preprocessor.
So, as a rule, if something doesn't compile when you input it directly, it won't when generated by the preprocessor either.
There are some caveats to its use (e.g. you've got to jump through some hoops to concatenate the results of other macro expansions), but the GCC docs discuss the basic form:
http://gcc.gnu.org/onlinedocs/cpp/Concatenation.html
http://en.wikipedia.org/wiki/C_preprocessor#Token_concatenation