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

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

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__ (~)

Примечание: На самом деле сама ссылка, которую вы опубликовали, утверждает это. Я проверю ссылку на это в стандарте.