マクロでオブジェクト指向
- boost::typeofのC++標準における実装の中で使われている
- 「オブジェクト」とは型名(のようなトークン)の後にデータメンバのインスタンス(のようなトークン)の続いた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;
}