マクロでオブジェクト指向

  • boost::typeofC++標準における実装の中で使われている
  • 「オブジェクト」とは型名(のようなトークン)の後にデータメンバのインスタンス(のようなトークン)の続いたSequenceと定義する
    • 例: (YOUR_CLASS)(data1)(data2)
  • メンバ関数」は型名の後にアンダースコアと関数名を付けたもので、呼び出しの最初の引数はオブジェクト自身とする
    • 例: YOUR_CLASS_MEMFUNC( (YOUR_CLASS)(data1)(data2), ... )


[]#include[][] <iostream>[]
[]#include[][] <boost/preprocessor/cat.hpp>[]
[]#include[][] <boost/preprocessor/seq.hpp>[]

[]// See: typeof_internals.htm.zip[]
[]// at http://boost-sandbox.sourceforge.net/vault/index.php[]

[]#define[] []CAT_3[]([]a[], []b[], []c[]) []BOOST_PP_CAT[]([]a[], []BOOST_PP_CAT[]([]b[],[]c[]))


[]#define[] []TYPENAME[]([]Obj[]) []BOOST_PP_SEQ_HEAD[]([]Obj[])

[]#define[] []VIRTUAL[]([]Fun[], []Obj[])\
[]CAT_3[]([]TYPENAME[]([]Obj[]), []_[], []Fun[])


[]// STUDENT's constructor (syntax sugar)[]
[]#define[] []STUDENT[]\
([]STUDENT[])

[]// STUDENT's override[]
[]#define[] []STUDENT_PRINT[]([]This[], []n[])\
[]std[]::[]cout[] << []n[] << []":SEITO"[] << []std[]::[]endl[];

[]// TEACHER's constructor (syntax sugar)[]
[]#define[] []TEACHER[]([]Kamoku[])\
([]TEACHER[])([]Kamoku[])

[]// TEACHER's override[]
[]#define[] []TEACHER_PRINT[]([]This[], []n[])\
[]std[]::[]cout[] << []n[] << []":TANTOU:"[] << []TEACHER_GET_KAMOKU[]([]This[]) << []std[]::[]endl[];

[]#define[] []TEACHER_GET_KAMOKU[]([]Param[])\
[]BOOST_PP_SEQ_ELEM[](1, []Param[])

[]// FOR_EACH helper function[]
[]#define[] []PRINT_SCHOOLROOM[]([]r[], []data[], []n[], []elem[])\
[]VIRTUAL[]([]PRINT[], []elem[])([]elem[], []n[])

[]// your application[]
[]#define[] []SAKURA_SCHOOL[] ([]OBJ_TARO[])([]OBJ_SAKAMOTO[])([]OBJ_ENDOU[])
[]#define[] []OBJ_TARO[] []STUDENT[]
[]#define[] []OBJ_SAKAMOTO[] []TEACHER[]([]"KOKUGO"[])
[]#define[] []OBJ_ENDOU[] []TEACHER[]([]"RIKA"[])

[]int[] []main[]()
{
[]BOOST_PP_SEQ_FOR_EACH_I[]([]PRINT_SCHOOLROOM[], ~, []SAKURA_SCHOOL[])
[]// expands to[]
[]// std::cout << 0 << ":SEITO" << std::endl; std::cout << 1 << ":TANTOU:" << "KOKUGO" << std::endl; std::cout << 2 << ":TANTOU:" << "RIKA" << std::endl; []

[]std[]::[]cin[].[]get[]();
[]return[] 0;
}