Assume we have a #define FOO(x,y) something.
I want to construct such macro #define BAR that BAR(x)(y) would call FOO(x,y). How can I do it, if it's possible at all?
I tried following:
#define BAR(x) FOO(x, BAR_
#define BAR_(y) y)
But got:
error: unterminated argument list invoking macro "FOO"
Here's a MCVE:
#include <iostream>
#define FOO(x,y) std::cout << x << y << '\n';
#define BAR(x) FOO(x, BAR0
#define BAR0(y) y)
#define STR(...) STR0(__VA_ARGS__)
#define STR0(...) #__VA_ARGS__
int main()
{
std::cout << STR( BAR(1)(2) );
}
Another attempt:
#define BAR FOO BAR0
#define BAR0(x) (x, BAR1
#define BAR1(y) y)
This one compiles, but leaves FOO (1, 2) unexpanded in the end.
MCVE:
#include <iostream>
#define FOO(x,y) std::cout << x << y << '\n';
#define BAR FOO BAR0
#define BAR0(x) (x, BAR1
#define BAR1(y) y)
#define STR(...) STR0(__VA_ARGS__)
#define STR0(...) #__VA_ARGS__
int main()
{
// Prints `FOO (1, 2)`, but I want `std::cout << 1 << 2 << '\n';`
std::cout << STR( BAR(1)(2) );
}
1. Dissecting the error
Let's start here:
#define BAR(x) FOO(x, BAR_
#define BAR_(y) y)
#define FOO(x,y) foo{x|y}
BAR(1)(2)
Note that I'm only going to use the preprocessor to debug the preprocessor (why do I need to build C++ programs, which invokes the preprocessor anyway, when I can simply just invoke the preprocessor? (That's rhetorical o/c; I'm just telling a story here)).
Here's how the CPP looks at this. We see BAR; that's a function-like macro. Interesting, but not actionable unless we see an open parentheses. Next, we see... an open parentheses. Now we're getting somewhere... we need to identify its arguments. So we keep scanning: BAR(1)... there... that's the matching open parentheses... looks like we're invoking with one argument. BAR it turns out is defined with one argument, so this works great.
Now we perform argument substitution... so we note that BAR's replacement list mentions its parameter (x) in a non-stringifying, non-pasting way. That means we should evaluate the corresponding argument (1), which is easy... that's just itself. That evaluation result then replaces the parameter in the replacement list, so we have FOO(1, BAR_. We're now done with argument substitution.
The next thing we need to do is rescan and further replacement. So we rescan... FOO, ah, yes. That's a function-like macro... FOO( ...and it's being invoked. Now we're getting somewhere... we need to identify its arguments. So, we keep scanning: FOO(1, BAR_(2)...and, suddenly we reach the end of the file. Huh? That's not right. FOO is being invoked; it's supposed to have a matching parentheses.
You might naively think that BAR_(2) should be invoked, but that's not how macros work. They evaluate outer-in, and the "in" (aka, argument tokens) only evaluates if there's a mention of the parameter in the replacement list, where said mention is not a stringification or paste.
Note that if FOO were not a function-like macro, this story would go an entirely different direction. In such a case, FOO( would simply be tokens the preprocessor doesn't care about... so by the time it sees BAR_(2), it will be invoking a macro. But there's another "cheat"; if FOO is passed over without actually invoking the macro FOO, the tokens would also be skipped over. In both cases, FOO(1, 2) will eventually be produced, which is what you want. But if you then want to evaluate FOO as a function-like macro, you have only one choice. You need a second pass; first pass actually allows your second argument in the sequence to be invoked to build your macro, and this pass must not allow FOO to be invoked. The second pass is needed to invoke it.
2. How to do this
Well, that's easy enough:
#define DELAY()
#define BAR(x) FOO DELAY() (x, BAR_
#define BAR_(y) y)
#define FOO(x,y) foo{x|y}
#define EVAL(...) __VA_ARGS__
BAR(1)(2)
EVAL(BAR(1)(2))
Here's how this is different (first line). After BAR's argument substitution, its replacement list is now FOO DELAY() (1, BAR_ instead of just FOO(1, BAR_. Now, during the rescan, it still sees FOO, which is still interesting... but the next token it sees is DELAY, not an open parentheses. So the CPP in this pass decides it's not invoking FOO and passes on it. After the full DELAY() expansion, which produces nothing, it then just sees (1, BAR_; the first three are just tokens. BAR_, however, is a macro invocation, and so goes the story... so the result of expanding BAR(1)(2) is to produce the tokens FOO(1, 2), error free. But that doesn't evaluate FOO.
The EVAL, however, accepts BAR(1)(2) as an argument. Its replacement list mentions its "parameter" (varying arg variant), so BAR(1)(2) is fully evaluated, producing FOO(1, 2). Then FOO(1, 2) is rescanned, which is when FOO actually gets invoked.
Related
I want to create a macro that replaces all calls to printf, more specifically mbedtls_printf (which behaves the exact sameway as printf) with nothing.
I know I can use #define mbedtls_printf to replace mbedtls_printf with nothing, but this will still leave the parameters/parenthesis intact.
Edit - I forgot to mention that mbedtls_printf is a macro that replaces itself with sgx_printf
I would go with:
#define printf(...) (0)
The benefit here is that it will continue to compile in cases where someone actually bothers to check the return from printf (rare but not unheard of).
The following works, at least with gcc 8. A brief search suggests that variadic macros were introduced with C99:
#define printf(...) do { } while (0)
int main()
{
printf("Hello %s?\n", "world");
return 0;
}
You want to use the ol' "do {} while (0)" trick, in order to avoid surprises like:
if (something)
printf("Something else");
will_this_be_invoked_or_not();
You can't make printf() disappear completely. Because this would make the next line a logical part of the preceding if statement. Hillarity ensues. That's why you still have to leave something in place.
If you completely no-op out the printf statements, there may be a bug lurking. Consider the following code:
printf("Result is %d\n", DoSomethingVeryImportant());
When you replace the printf call with a macro, you likely still want to make sure the inner function call to DoSomethingVeryImportant() is invoked. Otherwise, you've changed the logic of your program.
And I suppose you might want to have your mbedtls_printf actually call printf for debug builds, but be a no-op in a retail build.
If all of the above is of value, consider this as mbedtls_printf.h:
#ifndef MBEDTLS_PRINTF_H
#define MBEDTLS_PRINTF_H
#include <stdarg.h>
#include <stdio.h>
#ifdef DEBUG_BUILD
inline int printf_stub(const char* s, ...)
{
va_list args;
va_start(args, s);
vprintf(s, args);
va_end(args);
}
#define mbedtls_printf(...) printf_stub(__VA_ARGS__)
#else
inline int printf_stub(...){return 1;}
#define mbedtls_printf(...) printf_stub(__VA_ARGS__)
#endif
#endif
Then in code:
#include <iostream>
#include "mbedtls_printf.h"
int ImportantFunction()
{
std::cout << "Really important code" << std::endl;
return 42;
}
int main()
{
mbedtls_printf("Result of a very important step: %d\n", ImportantFunction());
mbedtls_printf("This just happened");
mbedtls_printf("Result of a another important step: ", 43, 44, ImportantFunction());
return 0;
}
The compiler will optimize out the empty function call and still invoke ImportantFunction() as it was doing originally.
I know I can use #define mbedtls_printf to replace mbedtls_printf with nothing, but this will still leave the parameters/parenthesis intact.
It's OK if the argument list remains, because then it will be treated as an expression. If we have an expression and we do nothing to it, then it will just be optimized out (on any decent compiler). Consider the following:
int x(char a, double b)
{
return printf("%c %f\n", a, b);
}
#define x
int main(void)
{
x('P', 3.14);
}
The compiler sees the following code for main:
('P', 3.14);
This expression evaluates to 3.14 (the comma operator returns its right-hand operand). Such an expression is quietly optimized.
Just use a lambda: (Variadic macros since C99)
#define printf(...) []{}()
What this does is simply replace the printf() calls to []{}()... This just means an empty function call... which can be formatted to be like this:
#define printf(...) [] { \
}()
Or, even this suffices:
// Replacing printf() with an empty function that just takes variadic arguments
#define printf [](...){}
Edit: You can also use:
#define printf void(0)
I have been trying to use variadic macros to reduce redundant code in some SFINAE patterns I am using. Specifically, I would like to generate function definitions using variadic macros. (This question is not about SFINAE). For my application, I would like write a wrapper function that calls an existing member function. The actual application requires that I produce a templated struct with SFINAE specialization so there is some repetitive stuff that would be great to just have a macro take care of generating the struct and function. OK that is the motivation.
The following example dispenses with all of the SFINAE stuff and simply defines a struct with three static functions (f0, f1, f2) with different parameter lists, and tries to call these functions through global macro generated function. Why would you want to do this?? You wouldn't. But this is just to illustrate the problem that I was having for the SFINAE application.
#include<iostream>
struct Foo
{
static void f0()
{
std::cout<<"f0() called"<<std::endl;
}
static void f1(int a)
{
std::cout<<"f1("<<a<<") called"<<std::endl;
}
static double f2(int a, double b)
{
std::cout<<"f2("<<a<<","<<b<<") called"<<std::endl;
return a*b;
}
};
#define VA_LIST(...) __VA_ARGS__
#define FUNCTION_WRAPPER(NAME,RTYPE,PARAMS,ARGS)\
RTYPE NAME(PARAMS)\
{\
return Foo::NAME(ARGS);\
}
FUNCTION_WRAPPER(f0,void,VA_LIST(),VA_LIST())
FUNCTION_WRAPPER(f1,void,VA_LIST(int a),VA_LIST(a))
FUNCTION_WRAPPER(f2,double,VA_LIST(int a, double b), VA_LIST(a, b))
int main()
{
f0();
f1(1);
f2(1,4.2);
return 0;
}
OK. So the VA_LIST(...) __VA_ARGS__ enables the creation of a single variable list. The call:
FUNCTION_WRAPPER(f2,double,VA_LIST(int a, double b), VA_LIST(a, b))
utilizes to variable lists as argument 3 and 3. Note that the Parameter list and the Argument list have to be consistent with each other (i.e. variables passed in the Argument list better be declared in the Parameter list.
This seems to work for this example, although there are issues if we were to try to add an fixed argument to beginning of the call (e.g. Foo::NAME(fixedArg, ARGS) ). It appears that the ##__VA_ARGS trick to swallow the comma if the variable list is empty doesn't work with this approach.
So the questions I have is:
While this approach seems to work properly on both gcc and clang, I can't find any similar examples that uses multiple variable lists in this manner...which makes me a little nervous. Is this a valid approach?
So what is actually happening in this approach? How is the FUNCTION_WRAPPER macro able to handle two variable lists? Are the PARAMS and ARGS macro arguments simply being expanded in the body of the macro, or is there something more complex happening here?
Is there a way to use the ## trick to swallow preceding commas? Placing the ## preceding the PARAMS and ARGS values in the macro body result in a compilation error, as does placing the ## in the VA_LIST.
Sample code for this last case is:
#define VA_LIST2(...) __VA_ARGS__
#define FUNCTION_WRAPPER2(NAME,RTYPE,PARAMS,ARGS)\
RTYPE NAME##_2(PARAMS)\
{\
return Foo::NAME(1,ARGS);\
}
FUNCTION_WRAPPER2(f2,double,VA_LIST2(double b), VA_LIST2(b))
The error for the insertion of ## into the FUNCTION_WRAPPER body is
error: pasting "," and "VA_LIST" does not give a valid preprocessing token
return Foo::NAME(1,##ARGS);\
The compilation error for the insertion of ## into the VA_LIST macro body is:
error: '##' cannot appear at either end of a macro expansion
#define VA_LIST2(...) ##__VA_ARGS__
^
How is the FUNCTION_WRAPPER macro able to handle two variable lists?
C preprocessor first recognizes arguments of a macro, then expands the arguments, then replaces the body of the macro with the expansion of arguments.
Because macro arguments are first "recognized" before expanded, macro expansion inside arguments resulting in a comma doesn't change the count of arguments.
Is there a way to use the ## trick to swallow preceding commas?
Be aware that it is still a GNU extension. Standard alternative to GCC's ##__VA_ARGS__ trick?
Yes, just make them to VA_ARGS so you can ## them.
#define VA_LIST2(...) __VA_ARGS__
#define ADD_ONE(...) 1,##__VA_ARGS__
#define FUNCTION_WRAPPER2(NAME,RTYPE,PARAMS,ARGS)\
RTYPE NAME##_2(PARAMS)\
{\
return Foo::NAME(ADD_ONE(ARGS));\
}
FUNCTION_WRAPPER2(f2,double,VA_LIST2(), VA_LIST2())
FUNCTION_WRAPPER2(f2,double,VA_LIST2(double b), VA_LIST2(b))
Is this a valid approach?
Sure, it's great. I would drop VA_LIST from the call. Lists in preprocessor are just done with (...). Then, just apply VA_LIST on the (...) argument.
#define VA_LIST(...) __VA_ARGS__
#define FUNCTION_WRAPPER(NAME,RTYPE,PARAMS,ARGS)\
RTYPE NAME(VA_LIST PARAMS) \
{ \
return Foo::NAME(VA_LIST ARGS); \
}
FUNCTION_WRAPPER(f0,void,(),())
FUNCTION_WRAPPER(f1,void,(int a),(a))
FUNCTION_WRAPPER(f2,double,(int a, double b), (a, b))
#define ADD_ONE(...) 1,##__VA_ARGS__
#define FUNCTION_WRAPPER2(NAME,RTYPE,PARAMS,ARGS)\
RTYPE NAME##_2(VA_LIST PARAMS) \
{ \
return Foo::NAME(ADD_ONE ARGS); \
}
FUNCTION_WRAPPER2(f2,double,(), ())
FUNCTION_WRAPPER2(f2,double,(double b), (b))
Anyway, double b .... b you are repeating yourself, however it is very clean and very flexible. You might want to see How to use variadic macro arguments in both a function definition and a function call? , c++ variadic macro: how to retrieve arguments values where I'm passing types and variable names as separate tokens and splitting them later differently depending on if it's function parameter list or call parameters.
I am trying to benchmark a large number of functions, and I have defined macros to generalise the time stamping. I have made a header file benchmarking.h as follows:
#include <chrono>
#include <iostream>
#define START(x) xstart = std::chrono::steady_clock::now()
#define END(x) xend = std::chrono::steady_clock::now()
#define TIME(x) xtime = std::chrono::duration_cast<std::chrono::nanoseconds>(xend-xstart).count()
#define PRINT(x) std::cout << #x << "(), " << xtime << std::endl
This for all macros, x is substituted with the function name, without parameter brackets. e.g PRINT(foobar); etc.
However, I have used the same macros for multiple function names, as I thought that I could substitute x multiple times.
i.e.
START(foobar);
// later...
START(func);
However, I get an error:
xstart’ has a previous declaration as ‘std::chrono::time_point<std::chrono::_V2::steady_clock, std::chrono::duration\<long int, std::ratio<1l, 1000000000l> > > xstart
It seems like I cannot reuse the variable once I have used it to define a function.
However, I never get this error with PRINT. So, is it because I am declaring variables?
I am basically trying to come up with a fast way to timestamp functions, so any other suggestions on how to achieve this quickly are welcome.
You need to use the macro token concatenation operator ##:
#define START(x) x ## start = std::chrono::steady_clock::now()
and similarly for the other macros.
When you just write xstart, the x is not replaced with the macro argument, but xstart is left as is. Argument substitution only operates on single identifiers; they cannot be part of a larger word.
I would like to ask why this code prints out 2 instead of 0. Doesn't #define "assign" values to the names of the macros and calculate also the result? How does it give this answer?
#include <iostream>
using namespace std;
#define A 0
#define B A+1
#define C 1-B
int main() {
cout << C<<endl;
return 0;
}
Macros are direct text replacements That means
#define C 1-B
becomes
1-A+1
and then A gets expanded so we have
1-0+1
which is 2. If you want 0 then stop using macros and instead use constant variables
const int A = 0;
const int B = A + 1;
const int C = 1 - B;
And now C is 0.
The preprocessor expands the C macro to 1-B, which expands to 1-A+1 which expands to 1-0+1 which equals 2. Don't think of it in terms of sequential assignment, but you can get the desired behavior by adding parenthesis around the macro definitions. Then the C macro would expand to (1-B), then (1-(A+1)) then (1-((0)+1)) which equals 0.
Edit:
As an example, the code snip below prints 42, even though BAR is "assigned" to FOO when FOO equals 17. This is because the expansion is deferred until it's actually used. On the cout line, BAR is still equal to FOO, but at that point, FOO is now 42, not 17. Note that it's bad practice to redefine a macro without first #undefining it.
#define FOO 17
#define BAR FOO
#define FOO 42
cout << BAR << endl;
Because C expands to 1-0+1
Preprocessor defines simply replace text and don't care about operator precedence or calculation rules.
Please note C++03! any C++11 solutions are not good for me, but do post them just for knowledge sake.
I know the preprocessor can do things like:
#define FOO 4
#if FOO == 4
cout<<"hi"<<endl;
#endif
What I need is:
#define BAR(X)\
#if X == 4\
cout<<"hi"<<endl;\
#endif
main.cpp
BAR(4)
I don't see why all the needed information wouldn't be available in preprocessor time.
So, Please tell me how to achieve this kind of behavior.
edit 1:
A normal if condition won't work for my case, because I also do things like:
#define BAR(X)\
#if X == 4\
int poop;
#elif
double poop;
#endif
As you've discovered, you can't do this in the way that you've attempted. Macro expansion simply doesn't have inline conditional evaluation, so you'd have to create multiple macros instead.
However, if you're just trying to "optimise" normal code flow, you can rely on your compiler's optimizations. Consider this:
if (true) {
std::cout << "Hi\n";
}
The resulting program will not have any conditional checks in it, because true is always truthy.
Similarly:
if (false) {
std::cout << "Hi\n";
}
The resulting program will not contain any code to produce output, because false is never truthy.
Similarly:
if (4 != 4) {
std::cout << "Hi\n";
}
The program will still not contain the std::cout code.
In many cases, you may use this fact to keep your code simple and achieve your desired effect:
#define BAR(X) \
if ((X) == 4) {
std::cout << "hi" << std::endl;\
}
The constraint here, of course, is that an if statement must be valid at the place you write BAR(5), or BAR(42) or BAR(999).
This is also flexible in that now you can use a runtime value (like BAR(i)) and, although the conditional can no longer be collapsed at compile-time, in such a case you'd have no reason to expect that anyway.
I take this approach in my logging macro: the macro, when called for LOG_LEVEL_DEBUG, expands to a conditional that is statically known never to match, in release builds.
The idea is to let the compiler do the optimising.
You're also going to want to consider using a little macro expansion trick to avoid problems with subsequent else clauses.
You can do this with the preprocessor if the domain of values for the conditional parameter is well-known (and preferably small). For example, supposing the parameter can only have the values 0 and 1:
#define DOIT_0(X)
#define DOIT_1(X) X
#define CONCAT_(X, Y) X ## Y
#define MAYBE(X) CONCAT_(DOIT_, X)
#define BAR(X) MAYBE(X)( cout<<"hi"<<endl; )
#define YESNO 0
BAR(YESNO)
Live on coliru.
Beware of unprotected commas in the argument to BAR.
For equality checks, again over a small range:
#define CONCAT3_(X,Y,Z) X ## Y ## Z
#define EQUAL_0_0(X) X
#define EQUAL_1_1(X) X
#define EQUAL_1_1(X) X
#define EQUAL_0_1(X)
#define EQUAL_0_2(X)
#define EQUAL_1_0(X)
#define EQUAL_1_2(X)
#define EQUAL_2_0(X)
#define EQUAL_2_1(X)
#define DO_IF_EQUAL(X, Y) CONCAT3_(EQUAL_, X, Y)
#define BAR(X) DO_IF_EQUAL(X, 2) ( std::cout << "hi\n"; )
If you can use Boost, you could do this with Boost.Preprocessor:
#define BAR(X) BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(X, 4), cout << "hi" << endl;)
Some answers here were better than others.
The one I accepted was posted by Christian Kiewiet in a comment, but it was the most accurate for my purpose.
Here is the expanded version:
useCases.h
enum UseCases{
useCase1=0,
useCase2,
useCaseNumber//always last for iterations
}
specializer.h
#include "useCases.h"
<template UseCases theCase>
struct StaticCase{
//empty, thus accidents calling from this can't happen
}
//specialization
template<>
class StaticCase<UseCases::useCase1>{
typedef int T;
static foo(T arg){cout<<"case1";};
}
template<>
class StaticCase<UseCases::useCase2>{
typedef double T;
static foo(){cout<<"case2";};
}
Now, I can do
#define BAR1(useCase) StaticCase<useCase>::foo();
or
#define BAR2(useCase) StaticCase<useCase>::T var;
and the call:
BAR1(UseCases::useCase1)//output - case1
BAR1(UseCases::useCase2)//output - case2