Что означает тильда (~) в макросах? - PullRequest
37 голосов
/ 25 июня 2011

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

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

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

Ответы [ 3 ]

30 голосов
/ 25 июня 2011

На вводной странице 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] ~ - не совсем произвольный выбор. И @, и $ могли бы быть хорошим выбором, за исключением того, что они технически не являются частью базового набора символов, который должны поддерживать реализации C ++. Идентификатор, такой как игнорируемый, может подвергаться расширению макросов, что приводит к неожиданным результатам.

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

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

4 голосов
/ 25 июня 2011

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

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

3 голосов
/ 25 июня 2011

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

_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~)

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

...