If I wanted to, could I just use only macros instead of using templates or functions without breaking anything?
Scoping could be an issue:
#include <iostream>
#define PRINT_VAR(x) std::cout << x << std::endl;
int main() {
int a = 5;
{
int b = 10;
PRINT_VAR(a);
PRINT_VAR(b);
}
PRINT_VAR(a);
// PRINT_VAR(b); // This would cause a compilation error if uncommented
return 0;
}
But this is the case with functions as well. However macros may lead to multiple execuations like this:
#include <iostream>
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int main() {
int x = 5;
int y = 10;
int z = MAX(x++, y++);
std::cout << "x: " << x << ", y: " << y << ", z: " << z << std::endl;
return 0;
}
What do you think the output here would be?
Answer
This is the output you get:
x: 6, y: 12, z: 11
This is because how the macro works is by replacing MAX with what it stand for, so z = MAX(x++, y++)
becomes z = ((x++) > (y++) ? (x++) : (y++))
and if x = 5 and y = 10, in the evaulation x should become x++ i.e. 6 and similarly y becomes 11 and 6 > 11 is false so y is incremented again so it becomes 12. But the value assigned to z is not post the second incrementation but just before it, hence z = 11.
Now what if z
is calculated as:
int z = MAX(++x, ++y);
Will the output be same as above?
Answer
No, what you will get now is:
x: 6, y: 12, z: 12
But why? Becuase the order of operations in x++
is different from ++x
. In
the first case, the value is assigned to z, then it is incremented. But in the second case, the
value assigned is after it is incremented.