Boost.PreprocessorのBOOST_PP_FORの実装の概要

  • マクロは再帰的に呼び出すと展開されないので、その場合は同じ機能を持つ違う名前の(違う数字が後ろについた)マクロを呼び出す
  • boostの実装は、展開されないことを逆手にとって再帰呼び出しを検出し、上記の作業を自動化しているようだ


[]// if-like[]
[]// 連結(##)は、実引数の展開を抑止するので[]
[]// まず評価してからBOOST_PP_IIF_Iに渡す[]
[]#define[] []BOOST_PP_IIF[]([]bit[], []t[], []f[]) []BOOST_PP_IIF_I[]([]bit[], []t[], []f[])
[]#define[] []BOOST_PP_IIF_I[]([]bit[], []t[], []f[]) []BOOST_PP_IIF_[] []## bit(t, f)[]
[]#define[] []BOOST_PP_IIF_0[]([]t[], []f[]) []f[]
[]#define[] []BOOST_PP_IIF_1[]([]t[], []f[]) []t[]

[]// eval_if-like[]


[]#define[] []BOOST_PP_EXPR_IIF[]([]bit[], []expr[]) []BOOST_PP_EXPR_IIF_I[]([]bit[], []expr[])
[]#define[] []BOOST_PP_EXPR_IIF_I[]([]bit[], []expr[]) []BOOST_PP_EXPR_IIF_[] []## bit(expr)[]
[]#define[] []BOOST_PP_EXPR_IIF_0[]([]expr[])
[]#define[] []BOOST_PP_EXPR_IIF_1[]([]expr[]) []expr[]

[]#define[] []BOOST_PP_TUPLE_EAT_2[]([]a[], []b[]) []/* nothing */[]
[]#define[] []BOOST_PP_TUPLE_EAT_4[]([]a[], []b[], []c[], []d[]) []/* nothing */[]

[]// static_cast<bool>-like[]
[]#define[] []BOOST_PP_BOOL[]([]x[]) []BOOST_PP_BOOL_I[]([]x[])
[]#define[] []BOOST_PP_BOOL_I[]([]x[]) []BOOST_PP_BOOL_[] []## x[]
[]#define[] []BOOST_PP_BOOL_0[] 0
[]#define[] []BOOST_PP_BOOL_1[] 1
[]#define[] []BOOST_PP_BOOL_2[] 1
[]#define[] []BOOST_PP_BOOL_3[] 1
[]// ...[]

[]// for-like[]
[]#define[] []BOOST_PP_FOR_1[]([]s[], []p[], []o[], []m[]) \
[]BOOST_PP_FOR_1_C[]([]BOOST_PP_BOOL[]([]p[](2, []s[])), []s[], []p[], []o[], []m[])
[]#define[] []BOOST_PP_FOR_1_C[]([]c[], []s[], []p[], []o[], []m[]) \
[]BOOST_PP_IIF[]([]c[], []m[], []BOOST_PP_TUPLE_EAT_2[])(2, []s[]) \
[]BOOST_PP_IIF[]([]c[], []BOOST_PP_FOR_2[], []BOOST_PP_TUPLE_EAT_4[])([]BOOST_PP_EXPR_IIF[]([]c[], []o[])(2, []s[]), []p[], []o[], []m[])
[]// if (c) m(2,s);[]
[]// if (c) BOOST_PP_FOR_2(o(2,s), p, o, m);[]

[]#define[] []BOOST_PP_FOR_2[]([]s[], []p[], []o[], []m[]) \
[]BOOST_PP_FOR_2_C[]([]BOOST_PP_BOOL[]([]p[](3, []s[])), []s[], []p[], []o[], []m[])
[]#define[] []BOOST_PP_FOR_2_C[]([]c[], []s[], []p[], []o[], []m[]) \
[]BOOST_PP_IIF[]([]c[], []m[], []BOOST_PP_TUPLE_EAT_2[])(3, []s[]) \
[]BOOST_PP_IIF[]([]c[], []BOOST_PP_FOR_3[], []BOOST_PP_TUPLE_EAT_4[])([]BOOST_PP_EXPR_IIF[]([]c[], []o[])(3, []s[]), []p[], []o[], []m[])

[]#define[] []BOOST_PP_FOR_3[]([]s[], []p[], []o[], []m[]) \
[]BOOST_PP_FOR_3_C[]([]BOOST_PP_BOOL[]([]p[](4, []s[])), []s[], []p[], []o[], []m[])
[]#define[] []BOOST_PP_FOR_3_C[]([]c[], []s[], []p[], []o[], []m[]) \
[]BOOST_PP_IIF[]([]c[], []m[], []BOOST_PP_TUPLE_EAT_2[])(4, []s[]) \
[]BOOST_PP_IIF[]([]c[], []BOOST_PP_FOR_4[], []BOOST_PP_TUPLE_EAT_4[])([]BOOST_PP_EXPR_IIF[]([]c[], []o[])(4, []s[]), []p[], []o[], []m[])

[]#define[] []BOOST_PP_FOR_4[]([]s[], []p[], []o[], []m[]) []BOOST_PP_FOR_4_C[]([]BOOST_PP_BOOL[]([]p[](5, []s[])), []s[], []p[], []o[], []m[])
[]#define[] []BOOST_PP_FOR_4_C[]([]c[], []s[], []p[], []o[], []m[]) \
[]BOOST_PP_IIF[]([]c[], []m[], []BOOST_PP_TUPLE_EAT_2[])(5, []s[]) \
[]BOOST_PP_IIF[]([]c[], []BOOST_PP_FOR_5[], []BOOST_PP_TUPLE_EAT_4[])([]BOOST_PP_EXPR_IIF[]([]c[], []o[])(5, []s[]), []p[], []o[], []m[])

[]//////////////////// MY APPLICATION ////////////////////[]

[]// increment[]
[]#define[] []BOOST_PP_INC[]([]x[]) []BOOST_PP_INC_I[]([]x[])
[]#define[] []BOOST_PP_INC_I[]([]x[]) []BOOST_PP_INC_[] []## x[]
[]#define[] []BOOST_PP_INC_0[] 1
[]#define[] []BOOST_PP_INC_1[] 2
[]#define[] []BOOST_PP_INC_2[] 3
[]#define[] []BOOST_PP_INC_3[] 4

[]// not three[]
[]#define[] []PRED_not_three[]([]r[], []state[]) []PRED_not_three_i[]([]state[])
[]#define[] []PRED_not_three_i[]([]state[]) []PRED_not_three_[] []## state ## _3[]
[]#define[] []PRED_not_three_0_3[] 1
[]#define[] []PRED_not_three_1_3[] 1
[]#define[] []PRED_not_three_2_3[] 1
[]#define[] []PRED_not_three_3_3[] 0

[]#define[] []OP_inc[]([]r[], []state[]) []BOOST_PP_INC[]([]state[])

[]#define[] []MACRO_plus[]([]r[], []state[]) []state[]+

[]#define[] []RESULT[] []BOOST_PP_FOR_1[](0, []PRED_not_three[], []OP_inc[], []MACRO_plus[])
[]// expands to 0+ 1+ 2+[]

[]#include[][] <iostream>[]

[]int[] []main[]()
{
[]std[]::[]wcout[] << []RESULT[] 3 << []std[]::[]endl[]; []// 0+ 1+ 2+ 3[]
[]std[]::[]wcin[].[]ignore[]();
[]return[] 0;
}