На вводной странице 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++. Такой идентификатор, как ignored, может быть подвергнут расширению макроса, что приведет к неожиданным результатам.
Таким образом, тильда — это просто заполнитель, потому что аргумент требуется, но в нем нет необходимости. Поскольку любой пользовательский идентификатор Wannabe может быть расширен, вам нужно использовать что-то еще.
Оказывается, что ~
в значительной степени не используется (двоичное отрицание не так часто используется) по сравнению, например, с +
или -
, поэтому вероятность путаницы невелика. Как только вы определились с этим, постоянное его использование придает тильде новое значение; например, использование operator<<
и operator>>
для потоковой передачи данных стало идиомой C++.
person
Matthieu M.
schedule
25.06.2011