Предположим, что вам необходимо сгенерировать семейство одноименных функций (или функций, имена которых незначительно отличаются), принимающих различное число аргументов. Такая задача часто встречается при написании функций-оберток, объектов-оберток и т. п. Вот примерный вид такого семейства:
void foo(int p1) { } void foo(int p1, int p2) { } void foo(int p1, int p2, int p3) { } void foo(int p1, int p2, int p3, int p4) { }
Ну и т. д. Обычно в таких случаях тела функций отличаются друг от друга незначительно. Можно, конечно, написать каждую из этих функций вручную (даже если их будет много). Но это утомительно и чревато ошибками, тем более что существует гораздо более простой, быстрый и достаточно безопасный (с точки зрения ошибок) способ сделать это. А именно – поручить компилятору. А точнее – препроцессору. Вот как эта задача решается с помощью библиотеки boost.preprocessor:
#define FOO_FN_GEN(z, n, _) void foo(BOOST_PP_ENUM_PARAMS(n, int p)) \ {\ } BOOST_PP_REPEAT_FROM_TO(1, 5, FOO_FN_GEN, _)
Результатом выполнения этого кода будет в точности приведенный выше набор функций. Теперь подробней о макросах. Ключевым (с точки зрения генерации) макросом здесь является разновидность макроса BOOST_PP_REPEAT – BOOST_PP_REPEAT_FROM_TO. Этот макрос выполняет некоторый макрос (в данном случае заданный третьим аргументом) заданное количество раз. Исполняемый макрос (в примере - FOO_FN_GEN) должен принимать на вход три аргумента. Первый (z) – используется для внутренних нужд библиотеки, второй (n) – текущее значение итерации. Третий – нечто, переданное последним аргументом в группу макросов BOOST_PP_REPEAT.