Ответ 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>>
для потоковой передачи данных стало идиомой С++.