Вот ответ от libc6
!
Взглянув на /usr/include/x86_64-linux-gnu/bits/byteswap.h
, я нашел трюк, который вы искали.
Несколько критиков предыдущих решений:
- Решение Кипа не позволяет вычислять выражение , которое, в конце концов, часто необходимо.
- Решение Коппро не позволяет присваивать переменную , так как выражения являются отдельными, но может вычисляться как выражение.
- Решение Стива Джессопа использует ключевое слово C ++ 11
auto
, это нормально, но не стесняйтесь использовать вместо него известный / ожидаемый тип .
Хитрость заключается в том, чтобы использовать как конструкцию (expr,expr)
, так и область действия {}
:
#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; \
} \
)
Обратите внимание на использование ключевого слова register
, это только подсказка компилятору.
Параметры макроса X
и Y
(уже) заключены в круглые скобки и приведено к ожидаемому типу.
Это решение работает должным образом с пре- и постинкрементным увеличением, поскольку параметры оцениваются только один раз.
В качестве примера, даже если он не был запрошен, я добавил оператор __x + __y;
, который позволяет сделать весь блок для оценки в качестве этого точного выражения.
Безопаснее использовать void();
, если вы хотите убедиться, что макрос не будет преобразовываться в выражение, поэтому является недопустимым там, где ожидается rvalue
.
Однако , решение не соответствует ISO C ++ , как будет жаловаться g++ -pedantic
:
warning: ISO C++ forbids braced-groups within expressions [-pedantic]
Чтобы немного отдохнуть g++
, используйте (__extension__ OLD_WHOLE_MACRO_CONTENT_HERE)
, чтобы новое определение гласило:
#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; \
} \
))
Чтобы еще больше улучшить мое решение, давайте используем ключевое слово __typeof__
, как видно из MIN и MAX в 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; \
} \
))
Теперь компилятор определит соответствующий тип. Это тоже расширение gcc
.
Обратите внимание на удаление ключевого слова register
, так как это будет следующее предупреждение при использовании с типом класса:
warning: address requested for ‘__x’, which is declared ‘register’ [-Wextra]