I have a 'system' to generate classes using macros (there is unfortunately no other way).
In some cases, for example for an initializer list, this leads to a trailing comma
that I'd like to get rid of:
#define REMOVE_TRAILING_COMMA(...) ?what to put here?
#define FOO a, b, c, d, e, f, g, h,
REMOVE_TRAILING_COMMA(FOO) --> expands to a, b, c, d, e, f, g, h
If it just removes the last argument that would be fine too, of course.
Aka if REMOVE_TRAILING_COMMA(a, b, c) expands to a, b.
The macro will always get at least two arguments, so the minimal case
would be: REMOVE_TRAILING_COMMA(a,) --> expands to a.
Is this even possible? I searched for a few hours with Google, but
nothing comes up.
I would be nice to use #define REMOVE_FIRST(a, ...) __VA_ARGS__, but that would require reversing macro arguments order. I do not see a way to do it (other then overloading it anyway). So overload the macro on count of arguments and enumerate each overload to remove trailing argument:
// example macro overoad for up to 9 args
// TODO: write REMOVE_TRAILING_COMMA_{1,2,3,4,5....} for each case
#define REMOVE_TRAILING_COMMA_8(_1,_2,_3,_4,_5,_6,_7,_8) \
_1,_2,_3,_4,_5,_6,_7
#define REMOVE_TRAILING_COMMA_9(_1,_2,_3,_4,_5,_6,_7,_8,_9) \
_1,_2,_3,_4,_5,_6,_7,_8
#define REMOVE_TRAILING_COMMA_N(_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) \
REMOVE_TRAILING_COMMA_##N
#define REMOVE_TRAILING_COMMA(...) \
REMOVE_TRAILING_COMMA_N(__VA_ARGS__,9,8,7,6,5,4,3,2,1)(__VA_ARGS__)
#define FOO a, b, c, d, e, f, g, h,
REMOVE_TRAILING_COMMA(FOO) --> expands to a, b, c, d, e, f, g, h
The following was added by Carlo Wood:
Thanks! I wrote a small program to generate the above, so it is
easy to increase the maximum number of arguments that this still works with:
#include <string>
#include <iostream>
#include <sstream>
std::string args1_N(int n)
{
std::ostringstream ss;
char const* prefix = "_";
for (int a = 1; a <= n; ++a)
{
ss << prefix << a;
prefix = ",_";
}
return ss.str();
}
int main()
{
int const max_args = 9;
for (int n = 1; n <= max_args + 1; ++n)
std::cout << "#define REMOVE_TRAILING_COMMA_" << n << "(" << args1_N(n) <<
") \\\n " << args1_N(n - 1) << std::endl;
std::cout << "#define REMOVE_TRAILING_COMMA_N(" << args1_N(max_args + 1) << ",N,...) \\\n" <<
" REMOVE_TRAILING_COMMA_##N\n";
std::cout << "#define REMOVE_TRAILING_COMMA(...) \\\n" <<
" REMOVE_TRAILING_COMMA_N(__VA_ARGS__";
for (int a = max_args + 1; a > 0; --a)
std::cout << "," << a;
std::cout << ")(__VA_ARGS__)" << std::endl;
}
Related
I want to write a macros to print pairs of {variable name, variable value}. The variables are supposed to be arguments of variadic macros.
I made a simple code, that produces compilation error: "expected expression" in cases when number of variables to print is less than maximum possible number.
#define IS_EMPTY(...) ( sizeof( (char[]){#__VA_ARGS__} ) == 1 )
#define PRINT_VAR(x) std::cout << "\"" << #x << "\": " << (x) << " ";
#define PRINT_VARS3(x, ...) {PRINT_VAR(x); }
#define PRINT_VARS2(x, ...) {PRINT_VAR(x); \
if constexpr (not IS_EMPTY(__VA_ARGS__)) PRINT_VARS3(__VA_ARGS__); }
#define PRINT_VARS1(x, ...) {PRINT_VAR(x); \
if constexpr (not IS_EMPTY(__VA_ARGS__)) PRINT_VARS2(__VA_ARGS__); }
#define PRINT_VARS(x, ...) {PRINT_VAR(x); \
if constexpr (not IS_EMPTY(__VA_ARGS__)) {\
PRINT_VARS1(__VA_ARGS__); \
} \
std::cout << "\n";}
int i = 100;
float j = 200.5;
int k = 300;
float l = -0.576f;
PRINT_VARS(i, j, k, l); // works fine
//PRINT_VARS(i, j); // compilation error
Thing that I cant understand, if I remove << (x) from second line, PRINT_VARS work with different number of arguments.
What is the reason and how to fix it?
Thank you!
Removing << (x) from the second line makes code compliable and working except it cant printout the variables values.
I expect the compiler not to check if constexpr branches at 0 condition. But it looks like empty
VA_ARGS passed to PRINT_VAR macros that leads to this error.
I have tried this code with gcc12 and clang14 compilers.
These are the requirements for my program. Code a program that will find the minimum, maximum, and sum of two integers and of three integers. Use 1 overloaded function for each of min, max, & sum. I have gotten most of it done, but dont know how to add an overload function. here is my code
#include <iostream>
using namespace std;
int main(){
int num1, num2;
cout<<"Enter first number: ";
cin>>num1;
cout<<"Enter second number: ";
cin>>num2;
cout<<"Sum of " << num1<< " and " <<num2<<" is: "<<(num1+num2)<<endl;
if (num1>num2)
{
cout << "The max is " << num1<< " and the min is " << num2<< endl;
}
else
{
cout<< num2 << " is the max, and " <<num1 <<" is the min"<<endl;
}
return 0;
}
The idea here is to separate the code into functions, and more specifically, to two different functions, with the same name, but with a different parameters (this means that this function has a different signature, and this is how the compiler distinguish one function to another!).
The code should look like that:
int add(int a, int b)
{
return a + b;
}
int add(int a, int b, int c)
{
return a + b + c;
}
int max(int a, int b)
{
return (a > b) ? a : b;
}
int max(int a, int b, int c)
{
return max(a, max(b, c));
}
Notice the little "trick" (which is recommended), that I have used the 2-argument max in the 3-argument max, instead of re-implement the same logic twice. In this way, if you have a bug, you will have a bug in both, but if you fix it, it will be fixed in both at the same time. This is true for many other type of functions!
Also, denote the (expression) ? (value_1) : (value_2) which is a short version for if assignment, which can be used when assigning variables or when returning a value, and are in common use.
P.S you can make in such a way an overload for any number of arguments, and for any type that has the operator< (although it does contain a problem, if the arguments are not from the same type!), using:
template <typename T>
T max(T a, T b)
{
return (a > b) ? a : b;
}
template <typename T, typename... Ts>
T max(T a, Ts... others)
{
const T max_of_others = max(others...);
return (a > max_of_others) ? a : max_of_others;
}
int main()
{
std::cout << "max of 1-6 is: " << max(1, 6, 3, 4, 5, 2) << std::endl;
}
But it is an overkill here! (just good to know for the future!)
Is there a way to make macro using #define, which will take two arguments and "return" string in specified format with values of given arguments?
Something like this:
#define MACRO( x, y ) ( "OK ", x, " ", y, " \a\b" ) // i know this doesn't work
int main ()
{
int a = 3,
b = -1;
std::cout << MACRO( a, b ) << std::endl; // this should print following string: "OK 3 -1 \a\b"
return 0;
}
I need to understand how this code works:
#define foo1( a ) (a * a) // How does this work?
inline int foo2( int a ) { return (a * a); }
int goo1( int x ) { return foo1(foo2(x)); }
int goo2( int& x ) { return x = foo2(foo1(x)); }
int goo3( int& x, int y ) { return foo2(foo1(y + 1)); }
void goo4( int& x, int y ) { x = foo1(foo2(y + 1)); }
int main(){
int i = 2, j = 1, a = 2+3;
cout << "foo1 = " << foo1( 1+2 ) << "\n"; // How does this work?
cout << "foo2 = " << foo2( 2 + 1 ) << "\n";
cout << "goo1 = " << goo1( i ) << "\n";
cout << "goo2 = " << goo2( j ) << "\n";
cout << "goo3 = " << goo3( i, j ) << "\n"; // How does this work?
goo4( i, j );
cout << " i = " << i << " j = " << j << "\n";
}
But I do not seem to be able understand the behaviour of this function:
#define foo1( a ) (a * a)
and hence I don't understand the output of these two function calls:
foo1( 1+2 )
goo3( i, j )
This is the output of the program:
foo1 = 5
foo2 = 9
goo1 = 16
goo2 = 1
goo3 = 9
i = 16 j = 1
I can't see why foo1 is not behaving like foo2. Would someone explain to me how this #define macro works?
NOTE: I must not change the code, I am only trying to understand the output.
Well, it's really simple.
foo1( 1 + 2 )
will turn into:
( 1 + 2 * 1 + 2 )
which is actually:
1 + 2 + 2 = 5
This is how macros work.
Macros are not functions.
Macros do TEXT replacement. So when you have
#define foo1( a ) (a * a)
any instance of foo1( ... ) with anything between then parenthesis will be expanded AS TEXT, not as an expression. So when you have foo1( 1 + 2 ) it turns into ( 1 + 2 * 1 + 2 )
Macro is not a function.
The compiler will expand all macros and then compile it. To see the expanded code, you can use the following command using -E option in gcc:
gcc -E <source code> -o <preprocessed file name>
Or in Visual C++, under Configuration Properties->C/C++->Preprocessor, set "Generate Preprocessed File".
BTW, your macro is problematic.
You should use
#define foo1( a ) ((a) * (a))
instead of
#define foo1( a ) (a * a)
The difference is, the foo1 defined by #define is NOT a function, while foo2 is.
In compilation process, the compiler will replace the foo1(parameter) keyword in your code with (parameter * parameter).
Meaning,
cout << "foo1 = " << foo1( 1+2 ) << "\n"; // How does this work?
will be replaced by the following code,
cout << "foo1 = " << ( 1+2 * 1+2 ) << "\n"; // How does this work?
(Because the parameter here is 1+2, instead of 3.)
The result is 1+2 * 1+2, which is 5.
Now let look at foo2, since it is an inline function, the compiler will not replace it. When your code is compiled into an executable file, and the executable file is executed, the 2 + 1 expression will be calculated first, and the result, 3, will then be passed to foo2().
In conclusion, the difference really lies in the compilation of your code. You may need more knowledge on what happens there.
I can define a macros which print only fixed variable count, for example:
#define PRINT_PARAMS(param) std::cout << "test: " << std::string( #param ) << " = " << param << "\n";
// using:
int varI = 5;
PRINT_PARAMS( varI );
// output:
test: varI = 5
How to define a macros which will do something like that:
PRINT_PARAMS( varI1, strValue2, floatValue3, doubleValue4 );
// output:
varI1 = 5, strValue2 = some string, floatValue3 = 3.403f, ....
I mean any number of input parameters.
#include <string>
#include <iostream>
//"for each" macro iterations
#define FE_1(Y, X) Y(X)
#define FE_2(Y, X, ...) Y(X)FE_1(Y, __VA_ARGS__)
#define FE_3(Y, X, ...) Y(X)FE_2(Y, __VA_ARGS__)
#define FE_4(Y, X, ...) Y(X)FE_3(Y, __VA_ARGS__)
#define FE_5(Y, X, ...) Y(X)FE_4(Y, __VA_ARGS__)
//... repeat as needed
//the "for each" call
#define GET_MACRO(_1,_2,_3,_4,_5,NAME,...) NAME
#define FOR_EACH(action,...) \
GET_MACRO(__VA_ARGS__,FE_5,FE_4,FE_3,FE_2,FE_1)(action,__VA_ARGS__)
//function to print a single
#define PRINT_SINGLE(param) std::cout << "test: " << std::string( #param ) << " = " << param << "\n";
//function to print n amount
#define PRINT_PARAMS(...) FOR_EACH(PRINT_SINGLE,__VA_ARGS__)
int main(){
std::string s1 = "hello";
float f = 3.14;
int i = 42;
PRINT_PARAMS(s1,f,i)
}
Don't have a compiler to hand but was wondering if the following variadic macro would work (or at least help give you an idea.)
#define PRINT_PARAMS(param) std::cout << "test: " << std::string( #param ) << " = " << param << "\n";
#define PRINT_PARAMS(a, ...) { PRINT_PARAMS((a)); PRINT_PARAMS(__VA_ARGS__); }