Here is the answer coming from libc6 ! Looking at /usr/include/x86_64-linux-gnu/bits/byteswap.h , I found the trick you were looking for.
A few critics of previous decisions:
- Kip's solution does not allow evaluating an expression, which is ultimately often necessary.
- The coppro solution does not allow you to assign a variable, because the expressions are separate, but can be evaluated in the expression.
- Steve Jessop's solution uses the C ++ 11
auto keyword, this is great, but feel free to use a known / expected type.
The trick is to use both the (expr,expr) construct and the {} region:
#define MACRO(X,Y) \ ( \ { \ register int __x = static_cast<int>(X), __y = static_cast<int>(Y); \ std::cout << "1st arg is:" << __x << std::endl; \ std::cout << "2nd arg is:" << __y << std::endl; \ std::cout << "Sum is:" << (__x + __y) << std::endl; \ __x + __y; \ } \ )
Note the use of the register keyword, this is just a hint to the compiler. Macro parameters X and Y (already) surrounded in parentheses and casted for the expected type. This solution works correctly with pre-increment and post-increment, since the parameters are evaluated only once.
As an example, although not requested, I added the __x + __y; , which allows you to evaluate the entire block as an exact expression.
It is safer to use void(); if you want to make sure that the macro will not be evaluated in the expression, so it is illegal if rvalue is expected.
However , the solution does not meet the requirements of ISO C ++, as g++ -pedantic will complain:
warning: ISO C++ forbids braced-groups within expressions [-pedantic]
To give some g++ rest, use (__extension__ OLD_WHOLE_MACRO_CONTENT_HERE) so that the new definition reads:
#define MACRO(X,Y) \ (__extension__ ( \ { \ register int __x = static_cast<int>(X), __y = static_cast<int>(Y); \ std::cout << "1st arg is:" << __x << std::endl; \ std::cout << "2nd arg is:" << __y << std::endl; \ std::cout << "Sum is:" << (__x + __y) << std::endl; \ __x + __y; \ } \ ))
To improve my solution even a little more, use the __typeof__ keyword, as shown in MIN and MAX in C :
#define MACRO(X,Y) \ (__extension__ ( \ { \ __typeof__(X) __x = (X); \ __typeof__(Y) __y = (Y); \ std::cout << "1st arg is:" << __x << std::endl; \ std::cout << "2nd arg is:" << __y << std::endl; \ std::cout << "Sum is:" << (__x + __y) << std::endl; \ __x + __y; \ } \ ))
Now the compiler will determine the appropriate type. This is also a gcc extension.
Pay attention to the removal of the register keyword, because when used with a class type, it will have the following warning:
warning: address requested for '__x', which is declared 'register' [-Wextra]