Why and when to use __noop? - c++

I was reading about __noop and the MSDN example is
#if DEBUG
#define PRINT printf_s
#else
#define PRINT __noop
#endif
int main() {
PRINT("\nhello\n");
}
and I don't see the gain over just having an empty macro:
#define PRINT
The generated code is the same. What's a valid example of using __noop that actually makes it useful?

The __noop intrinsic specifies that a function should be ignored and the argument list be parsed but no code be generated for the arguments. It is intended for use in global debug functions that take a variable number of arguments.
In your case the argument is an obviously side effect free expression that can be easily optimized out, so it doesn't matter.
But if the argument expression has side effects or is so complex that the compiler can't prove that it terminates normally and has no side-effects then using __noop prevents the potentially expensive evaluation of that expression.
The second benefit is that it behaves like a function call with a variable number of arguments syntactically. So substituting it for a function call doesn't affect the parsing of the program. With some other replacements (like the empty string), that might be a problem in some situations.

#define PRINT
extern int some_complicated_calculation();
PRINT("%d\n", some_complicated_calculation());
would call the function even though you don't want the result.
Using __noop, the function won't be called.
You could (assuming the compiler supports variadic macros) define PRINT to ignore the arguments; but then they won't be parsed at all, and may become invalid if you change the code around them without compiling the variant that defines PRINT to do something. Using __noop, the arguments are still parsed, so are more likely to remain valid.

Related

C++ Directive With void(0)

What is the purpose of having a directive like below?
#define TEST_CONDITION(con) !(con) ? (void)0:
In particular, I see this called at the start of other directives.
For example,
#define OTHER_CONDITION(..)
TEST_CONDITION(someFunction)
ANOTHER_DIRECTIVE(...)
Doesn't TEST_CONDITION just no-op or a boolean is returned that isn't used in these cases?
Expand the macro, and it becomes clearer. I'll also use some formatting to keep the code readable, and I assume that the lack of some essential escape characters is not meant to be part of the example. OTHER_CONDITION becomes:
!(someFunction)
? (void)0
: ANOTHER_DIRECTIVE(...)
So, the expression someFunction is executed, and if it is true, then ANOTHER_DIRECTIVE(...) (or whatever it expands to) is executed. Otherwise nothing is executed.
Simpler way to write OTHER_CONDITION could be:
#define OTHER_CONDITION(..) if(someFunction) ANOTHER_DIRECTIVE(...)
This simplification lacks some restrictions that TEST_CONDITION provides:
TEST_CONDITION makes it impossible to append an else branch.
TEST_CONDITION makes it ill-formed to use a non-void ANOTHER_DIRECTIVE(...).

Why won't my variadic macro accept no arguments correctly?

Overloading Macro on Number of Arguments
https://codecraft.co/2014/11/25/variadic-macros-tricks/
I've been looking at the two links above, trying to get the following code to work:
#define _GET_NUMBER(_0, _1, _2, _3, _4, _5, NAME, ...) NAME
#define OUTPUT_ARGS_COUNT(...) _GET_NUMBER(_0, ##__VA_ARGS__, 5, 4, 3, 2, 1, 0)
...
cout << OUTPUT_ARGS_COUNT("HelloWorld", 1.2) << endl;
cout << OUTPUT_ARGS_COUNT("HelloWorld") << endl;
cout << OUTPUT_ARGS_COUNT() << endl;
This compiles, runs, and gives the following output:
2
1
1
I can not for the life of me figure out why the call OUTPUT_ARGS_COUNT() is giving me 1 instead of 0. I have an ok understanding of the code I'm trying to use, but it's a tad greek to me still so I guess it's possible that I'm not applying something correctly despite the fact I literally copied and pasted the example code from the link on stack overflow.
I'm compiling using g++ 5.4.0 20160609.
Any ideas or additional resources you can point me to would be greatly appreciated.
You can see at http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html:
Second, the ‘##’ token paste operator has a special meaning when placed between a comma and a variable argument. If you write
#define eprintf(format, ...) fprintf (stderr, format, ##__VA_ARGS__)
and the variable argument is left out when the eprintf macro is used, then the comma before the ‘##’ will be deleted. This does not happen if you pass an empty argument, nor does it happen if the token preceding ‘##’ is anything other than a comma.
eprintf ("success!\n")
→ fprintf(stderr, "success!\n");
The above explanation is ambiguous about the case where the only macro parameter is a variable arguments parameter, as it is meaningless to try to distinguish whether no argument at all is an empty argument or a missing argument. CPP retains the comma when conforming to a specific C standard. Otherwise the comma is dropped as an extension to the standard.
So, (unless appropriate extension used) OUTPUT_ARGS_COUNT() is counted as 1 empty argument (comma kept with ##__VA_ARGS__).
The C standard specifies
If the identifier-list in the macro definition does not end with an ellipsis, [...]. Otherwise, there shall be more arguments in the invocation than there are parameters in the macro definition (excluding the ...)
(C2011 6.10.3/4; emphasis added)
C++11 contains language to the same effect in paragraph 16.3/4.
In both cases, then, if your macro invocation were interpreted to have zero arguments then your program would be non-conforming. On the other hand, the preprocessor does recognize and support empty macro arguments -- that is, arguments consisting of zero preprocessing tokens. In principle, then, there is an ambiguity here between no argument and a single empty argument, but in practice, only the latter interpretation results in a conforming program.
That g++ opts for the latter interpretation (the other answer quotes its documentation to that effect) is thus reasonable and appropriate, but it is not safe to rely upon it if you want your code to be portable. A compiler that takes the alternative interpretation would behave differently, possibly by providing the behavior you expected, but also possibly by rejecting the code.

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.

what is the use of "static_cast<void>" in macro?

I'm seeing a macro definition like this:
#define ASSERT_VALID_PARAM(param, assertion) { static_cast<void>(param); if (!(assertion)) { throw InvalidParamError(#param, #assertion, __FILE__, __PRETTY_FUNCTION__, __LINE__); } }
I'm not able to figure out the need of static_cast<void>(param) here.
Any idea on why this is needed?
This macro is designed to validate a certain real parameter passes a certain validation rule(s). The logic part of the macro is composed of 2 parts:
Validate that param is a real parameter, with a valid name. This is done by using the static_cast, and if an illegal name is used, a compile time error will be generated.
Validate the "truthyness" of assertion. This is done with a simple negating if statement.
If the param is a valid name, and the assertion fails (assertion == false), an InvalidParamError is thrown, using the passed in parameters as strings (using the Stringizing operator #) to initialize the error object.
Since the actual usage of the param parameter in the macro is only as a string, it has to be validated using actual code. Since no real operation is needed the static_cast is used, which discards the result and can potentially be optimized out. Without that check, you could pass any value which would make the information in the assertion meaningless.
it is the 'c++ way' of writing
(void)param;
it makes 'use' of the variable and thus disables the compiler warning for unused variable
static_cast<void>(param); will evaluate the param and discard the result.
If you don't add the cast to void:
you may get warnings saying you are ignoring the result of
expression.
Even if you pass some illegal code (for example a statement instead of expression) as argument, compiler will accept it happily.
From cppreference
4) If new_type is the type void (possibly cv-qualified), static_cast
discards the value of expression after evaluating it.

C++ Preprocessor Standard Behaviour

I'm studying the C++ standard on the exact behaviour the preprocessor (I need to implement some sort of C++ preprocessor). From what I understand, the example I made up (to aid my understanding) below should be valid:
#define dds(x) f(x,
#define f(a,b) a+b
dds(eoe)
su)
I expect the first function like macro invocation dds(eoe) be replaced by f(eoe, (note the comma within the replacement string) which then considered as f(eoe,su) when the input is rescanned.
But a test with VC++2010 gave me this (I told the VC++ to output the preprocessed file):
eoe+et_leoe+et_l
su)
This is counter-intuitive and is obviously incorrect. Is it a bug with VC++2010 or my misunderstanding of the C++ standard? In particular, is it incorrect to put a comma at the end of the replacement string like I did? My understanding of the C++ standard grammar is that any preprocessing-token's are allowed there.
EDIT:
I don't have GCC or other versions of VC++. Could someone help me to verify with these compilers.
My answer is valid for the C preprocessor, but according to Is a C++ preprocessor identical to a C preprocessor?, the differences are not relevant for this case.
From C, A Reference Manual, 5th edition:
When a functionlike macro call is encoutered, the entire macro call is
replaced, after parameter processing, by a copy of the body. Parameter
processing proceeds as follows. Actual argument token strings are
associated with the corresponding formal parameter names. A copy of
the body is then made in which every occurrence of a formal parameter
name is replace by a copy of the actual parameter token sequence
associated with it. This copy of the body then replaces the macro
call.
[...] Once a macro call has been expanded, the scan for macro calls
resumes at the beginning of the expansion so that names of macros may
be recognized within the expansion for the purpose of further macro
replacement.
Note the words within the expansion. That's what makes your example invalid. Now, combine it with this: UPDATE: read comments below.
[...] The macro is invoked by writing its name, a left parenthesis,
then once actual argument token sequence for each formal parameter,
then a right parenthesis. The actual argument token sequences are
separated by commas.
Basically, it all boils down to whether the preprocessor will rescan for further macro invocations only within the previous expansion, or if it will keep reading tokens that show up even after the expansion.
This may be hard to think about, but I believe that what should happen with your example is that the macro name f is recognized during rescanning, and since subsequent token processing reveals a macro invocation for f(), your example is correct and should output what you expect. GCC and clang give the correct output, and according to this reasoning, this would also be valid (and yield equivalent outputs):
#define dds f
#define f(a,b) a+b
dds(eoe,su)
And indeed, the preprocessing output is the same in both examples. As for the output you get with VC++, I'd say you found a bug.
This is consistent with C99 section 6.10.3.4, as well as C++ standard section 16.3.4, Rescanning and further replacement:
After all parameters in the replacement list have been substituted and # and ##
processing has taken place, all placemarker preprocessing tokens are removed. Then, the
resulting preprocessing token sequence is rescanned, along with all subsequent
preprocessing tokens of the source file, for more macro names to replace.
To the best of my understanding there is nothing in the [cpp.subst/rescan] portions of the standard that makes what you do illegal, and clang and gcc are right in expanding it as eoe+su, and the MSC (Visual C++) behaviour has to be reported as a bug.
I failed to make it work but I managed to find an ugly MSC workaround for you, using variadics - you may find it helpful, or you may not, but in any event it is:
#define f(a,b) (a+b
#define dds(...) f(__VA_ARGS__)
It is expanded as:
(eoe+
su)
Of course, this won't work with gcc and clang.
Well, the problem i see is that the preprocessor does the following
ddx(x) becomes f(x,
However, f(x, is defined as well (even thou it's defined as f(a,b) ), so f(x, expands to x+ garbage.
So ddx(x) finally transforms into x + garbage (because you defined f(smthing, ).
Your dds(eoe) actually expands into a+b where a is eoe and b is et_l .
And it does that twice for whatever reason :).
This scenario you made is compiler specific, depends how the preprocessor chooses to handle the defines expansion.