Что означает Тильда (~) в макросах?
видел на этот сайт, код показывает вызовы макросов с использованием Тильды в круглых скобках:
HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~))
// ^^^
что это значит / делать? Я подозреваю, что это просто пустой аргумент, но я не уверен. Может быть, это специфично для C (99), как __VA_ARGS__
специфичен для C99 и существует в C++?
3 ответов
на странице введения Boost.Препроцессор, пример приведен в А. 4.1.1 Горизонтальные Повторения
#define TINY_print(z, n, data) data
#define TINY_size(z, n, unused) \
template <BOOST_PP_ENUM_PARAMS(n, class T)> \
struct tiny_size< \
BOOST_PP_ENUM_PARAMS(n,T) \
BOOST_PP_COMMA_IF(n) \
BOOST_PP_ENUM( \
BOOST_PP_SUB(TINY_MAX_SIZE,n), TINY_print, none) \
> \
: mpl::int_<n> {};
BOOST_PP_REPEAT(TINY_MAX_SIZE, TINY_size, ~) // Oh! a tilde!
#undef TINY_size
#undef TINY_print
объяснение приводится ниже:
процесс генерации кода запускается вызовом
BOOST_PP_REPEAT
, a высшего порядка макрос, который неоднократно вызывает макрос, названный его вторым аргументом (TINY_size
). Первый аргумент указывает количество повторных вызовов, а третий может быть любым данные; он передается без изменений вызываемому макросу. в этом случаеTINY_size
не использует эти данные, поэтому выбор для передачи~
был произвольным. [5]
(выделено мной)
и есть примечание:
[5]
~
не является полностью произвольным выбором. Оба!--7--> и$
возможно, это был хороший выбор, за исключением того, что они технически не являются частью базового набора символов, который реализует C++ требуются для поддержки. Идентификатор, подобный игнорируемому, может быть расширен макросом, что приведет к неожиданным результатам.
Тильда, таким образом, является просто держателем места, потому что аргумент необходим, но не нужен. Поскольку любой пользовательский идентификатор wannabe может быть расширен, вам нужно использовать что-то еще.
получается, что ~
в значительной степени не используется (двоичное отрицание не так часто называется) по сравнению с +
или -
например, так мало шансов на путаницу. Как только вы остановились на этом, использование его последовательно дает ему новая значение для Тильды; как использование operator<<
и operator>>
для потоковой передачи данных стала идиомой C++.
на ~
ничего не делает. Почти любой другой контент внутри этих скобок будет работать одинаково.
стержень этого трюка, чтобы проверить, является ли _TRIGGER_PARENTHESIS_
рядом с (~)
расширение _TRIGGER_PARENTHESIS_ __VA_ARGS__ (~)
. В любом случае, HAS_COMMA(...)
расширяет свои аргументы, либо 0
или 1
.
проверяемые аргументы помещаются между макросом и его круглыми скобками, макрос запускается только в том случае, если аргументы пусты:
_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~)
Примечание: На самом деле сама ссылка, которую вы опубликовали, утверждает это. Я проверю ссылку на это в стандарте.