Подтвердить что ты не робот

Что означает тильда (~) в макросах?

Посмотрите на этот сайт, код показывает макросы, используя тильду в круглых скобках:

HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~))
//                                          ^^^

Что это значит/делать? Я подозреваю, что это просто пустой аргумент, но я не уверен. Может быть, он специфичен для C (99), как __VA_ARGS__, специфичен для C99 и существует в С++?

4b9b3361

Ответ 1

На странице введения Boost.Preprocessor приведен пример в A.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, высшего порядка, который повторно вызывает макрос, названный его вторым аргументом (TINY_size). Первый аргумент указывает количество повторных вызовов, а третий может быть любыми данными; он передается без изменений на вызываемый макрос. В этом случае TINY_size не использует эти данные, поэтому выбор для прохождения ~ был произвольным. [5]

(акцент мой)

И есть примечание:

[5] ~ не является полностью произвольным выбором. И @, и $ могли бы быть хорошим выбором, за исключением того, что они технически не являются частью базового набора символов, который требуется для поддержки С++. Идентификатор, такой как игнорируемый, может подвергаться макроразложению, что приводит к неожиданным результатам.

Таким образом, тильда является просто владельцем места, потому что требуется аргумент, но нет необходимости. Поскольку любой пользовательский идентификатор wannabe может быть расширен, вам нужно использовать что-то еще.

Оказывается, что ~ в значительной степени не используется (двоякое отрицание не так часто называют) по сравнению с + или -, например, так что шансов на путаницу мало. Когда вы решитесь на это, использование его последовательно придаст ему новый смысл тильде; например, использование operator<< и operator>> для потоковой передачи данных стало идиомой С++.

Ответ 2

~ ничего не делает. Почти любой другой контент внутри этих круглых скобок будет работать одинаково.

Следствием этого трюка является проверка того, находится ли _TRIGGER_PARENTHESIS_ рядом с (~) в разложении _TRIGGER_PARENTHESIS_ __VA_ARGS__ (~). В любом случае HAS_COMMA(...) расширяет свои аргументы до 0 или 1.

Ответ 3

Аргументы, подлежащие тестированию, помещаются между макросом и его скобкой, макрос запускается только в том случае, если аргументы пусты:

_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~)

ПРИМЕЧАНИЕ. На самом деле указанная вами ссылка указала это. Я проверю ссылку на это в стандарте.