続コンパイルタイム・ポリモーフィズム

  • id:y-hamigaki:20060407に関連して
  • 特に、Metafunctionのカスタマイズが必要ない場合、継承階層が働くように、デフォルトの動作(メンバ関数を呼び出す等)はない方が良いと思う
    • 例えば、の一番上のboost_range_beginは、ある基底クラスがRangeとしてカスタマイズされていても、その派生クラスを全て食べてしまう
  • クラス内部のtypedefによってカスタマイズの方法を指定してもらうのはどうだろう
    • enumerate自体はボツになるかも

[]namespace[] []pstade[][] { [][]namespace[] []tomato[][] {[]

[]class[] []enumerate_access[]
[]{[]
[]public[][]: [][]// ←friendの動作が怪しいのであきらめる[]
[]template[][]< [][]class[] []T[][], [][]class[] []Functor[][] > [][]static[]
[]Functor[] []detail_call[][]([][]T[][]& [][]x[][], [][]Functor[] []fun[][])[]
[] {[]
[]return[] []x[][].[][]pstade_tomato_enumerate[][]([][]fun[][]);[]
[] }[]
[]};[]


[]namespace[] []enumerate_detail[][] {[]


[]// BOOST_MPL_HAS_XXX_TRAIT_DEFはVC++で動かないので注意[]
[]// ...http://lists.boost.org/Archives/boost/2005/10/95809.php[]
[]PSTADE_HAS_XXX[][]([][]pstade_tomato_enumerable[][])[]


[]struct[] []member_function[]
[] {[]
[]template[][]< [][]class[] []T[][], [][]class[] []Functor[][] > [][]static[]
[]Functor[] []call[][]([][]T[][]& [][]x[][], [][]Functor[] []fun[][])[]
[] {[]
[]return[] []enumerate_access[][]::[][]detail_call[][]([][]x[][], [][]fun[][]);[]
[] }[]
[] };[]


[]struct[] []adl_customization[]
[] {[]
[]template[][]< [][]class[] []T[][], [][]class[] []Functor[][] > [][]static[]
[]Functor[] []call[][]([][]T[][]& [][]x[][], [][]Functor[] []fun[][])[]
[] {[]
[]return[] []pstade_tomato_enumerate[][]([][]x[][], [][]fun[][], [][]overload[][]());[]
[] }[]
[] };[]


[]struct[] []boost_range[]
[] {[]
[]template[][]< [][]class[] []T[][], [][]class[] []Functor[][] > [][]static[]
[]Functor[] []call[][]([][]T[][]& [][]x[][], [][]Functor[] []fun[][])[]
[] {[]
[]typedef[] []typename[] []boost[][]::[][]range_result_iterator[][]<[][]T[][]>::[][]type[] []iter_t[][];[]
[]typedef[] []typename[] []boost[][]::[][]iterator_reference[][]<[][]iter_t[][]>::[][]type[] []ref_t[][];[]

[]BOOST_FOREACH[][] ([][]ref_t[] []val[][], [][]x[][]) {[]
[]if[][] (![][]fun[][]([][]val[][]))[]
[]return[] []fun[][];[]
[] }[]

[]return[] []fun[][];[]
[] }[]
[] };[]


[]template[][]< [][]class[] []T[][], [][]class[] []Functor[][] > [][]inline[]
[]Functor[] []aux[][]([][]T[][]& [][]x[][], [][]Functor[] []fun[][])[]
[] {[]
[]typedef[] []typename[]
[]boost[][]::[][]mpl[][]::[][]eval_if[][]< [][]has_pstade_tomato_enumerable[][]<[][]T[][]>,[]
[]boost[][]::[][]mpl[][]::[][]identity[][]<[][]member_function[][]>,[]
[]boost[][]::[][]mpl[][]::[][]if_[][]< [][]apple[][]::[][]is_boost_range[][]<[][]T[][]>, [][]// ←正確に判定することは不可能(あくまでサービス)[]
[]boost_range[][],[]
[]adl_customization[]
[] >[]
[] >::[][]type[] []impl_t[][];[]

[]return[] []impl_t[][]::[][]call[][]([][]x[][], [][]fun[][]);[]
[] };[]


[]} [][]// namespace enumerate_detail[]


[]template[][]< [][]class[] []Enumerable[][], [][]class[] []Functor[][] > [][]inline[]
[]Functor[] []enumerate[][]([][]Enumerable[][]& [][]e[][], [][]Functor[] []fun[][])[]
[]{[]
[]return[] []enumerate_detail[][]::[][]aux[][]([][]e[][], [][]fun[][]);[]
[]};[]


[]template[][]< [][]class[] []Enumerable[][], [][]class[] []Functor[][] > [][]inline[]
[]Functor[] []enumerate[][]([][]const[] []Enumerable[][]& [][]e[][], [][]Functor[] []fun[][])[]
[]{[]
[]return[] []enumerate_detail[][]::[][]aux[][]([][]e[][], [][]fun[][]);[]
[]};[]


[]// ある実装の例[]
[]//[]

[]namespace[] []child_windows_detail[][] {[]


[]template[][]< [][]class[] []Functor[][] >[]
[]struct[] []data[]
[] {[]
[]data[][]([][]Functor[] []fun[][]) :[]
[]m_fun[][]([][]fun[][]) []
[] { }[]

[]Functor[] []m_fun[][];[]
[] };[]


[]template[][]< [][]class[] []DataT[][] >[]
[]BOOL[] []CALLBACK[] []proc[][]([][]HWND[] []hWnd[][], [][]LPARAM[] []lParam[][])[]
[] {[]
[]BOOST_ASSERT[][]([][]diet[][]::[][]valid[][]([][]hWnd[][]));[]

[]DataT[][] *[][]pdata[][] = [][]reinterpret_cast[][]<[][]DataT[][] *>([][]lParam[][]);[]
[]return[] []tomato[][]::[][]boolean[][]([][]pdata[][]->[][]m_fun[][]([][]hWnd[][]));[]
[] }[]


[]template[][]< [][]class[] []Functor[][] >[]
[]Functor[] []enumerate[][]([][]HWND[] []hWndParent[][], [][]Functor[] []fun[][])[]
[] {[]
[]typedef[] []data[][]<[][]Functor[][]> [][]data_t[][];[]
[]data_t[] []data[][]([][]fun[][]);[]

[] ::[][]EnumChildWindows[][]([]
[]hWndParent[][],[]
[] &[][]proc[][]<[][]data_t[][]>,[]
[]reinterpret_cast[][]<[][]LPARAM[][]>(&[][]data[][])[]
[] );[]

[]return[] []data[][].[][]m_fun[][];[]
[] }[]


[]} [][]// namespace child_windows_detail[]


[]struct[] []child_windows[]
[]{[]
[]// メンバ関数pstade_tomato_enumerateを使って[]
[]// カスタマイズすることの表明[]
[]typedef[] []child_windows[] []pstade_tomato_enumerable[][];[]

[]explicit[] []child_windows[][]([][]HWND[] []hWndParent[][]) :[]
[]m_hWndParent[][]([][]hWndParent[][])[]
[] { }[]

[]private[][]:[]
[]HWND[] []m_hWndParent[][];[]

[]friend[] []class[] []enumerate_access[][];[]
[]template[][]< [][]class[] []Functor[][] >[]
[]Functor[] []pstade_tomato_enumerate[][]([][]Functor[] []fun[][]) [][]const[]
[] {[]
[]// クラス内に実装をなるべく書かない(自分の)流行[]
[]return[] []child_windows_detail[][]::[][]enumerate[][]([][]m_hWndParent[][], [][]fun[][]);[]
[] }[]
[]};[]


[]} } [][]// namespace pstade::tomato[]