// encode: shift_jis // 140行目から使い方サンプルがあります #include #include namespace mpl = boost::mpl; namespace bd { //-------------------------------------------------------------- // の he の方を指すポインタを模擬する場合の実装。 //-------------------------------------------------------------- template class bidi_ptr_left { friend traits; protected: typedef typename traits::left_type* pointer; typedef typename traits::left_type value_type; typedef typename traits::right_type owner_type; void assign( value_type* p ) { traits::assign_2(p, owner); } bidi_ptr_left( owner_type* o ) : owner(o) {} public: value_type& operator*() const { return *ptr; } value_type* operator->() const { return ptr; } private: owner_type* const owner; value_type* ptr; }; //-------------------------------------------------------------- // の she の方を指すポインタを模擬する場合の実装。 //-------------------------------------------------------------- template class bidi_ptr_right { friend traits; protected: typedef typename traits::right_type* pointer; typedef typename traits::right_type value_type; typedef typename traits::left_type owner_type; void assign( value_type* p ) { traits::assign_2(owner, p); } bidi_ptr_right( owner_type* o ) : owner(o) {} public: value_type& operator*() const { return *ptr; } value_type* operator->() const { return ptr; } private: owner_type* const owner; value_type* ptr; }; //--------------------------------------------- // 双方向ポインタ bidi_ptr<> // bidi_ptr // bidi_ptr // bidi_ptr // bidi_ptr // のいずれかの形式で使えます。 //--------------------------------------------- template class bidi_ptr : public mpl::if_c< boost::is_same::value, bidi_ptr_left, bidi_ptr_right >::type { friend class traits; typedef bidi_ptr this_type; typedef typename mpl::if_c< boost::is_same::value, bidi_ptr_left, bidi_ptr_right >::type parent_type; public: typedef typename parent_type::value_type value_type; typedef typename parent_type::pointer pointer; typedef typename parent_type::owner_type owner_type; bidi_ptr( owner_type* o ) : parent_type(o) {} this_type& operator=( pointer p ) { assign(p); return *this; } }; class left; template class bidi_ptr : public bidi_ptr_left { friend class traits; typedef bidi_ptr this_type; typedef bidi_ptr_left parent_type; public: typedef typename parent_type::value_type value_type; typedef typename parent_type::pointer pointer; typedef typename parent_type::owner_type owner_type; bidi_ptr( owner_type* o ) : parent_type(o) {} this_type& operator=( pointer p ) { assign(p); return *this; } }; class right; template class bidi_ptr : public bidi_ptr_right { friend class traits; typedef bidi_ptr this_type; typedef bidi_ptr_right parent_type; public: typedef typename parent_type::value_type value_type; typedef typename parent_type::pointer pointer; typedef typename parent_type::owner_type owner_type; bidi_ptr( owner_type* o ) : parent_type(o) {} this_type& operator=( pointer p ) { assign(p); return *this; } }; #define DEFINE_BIDI_PTR_TRAITS(TraitsName, LeftType, LeftField, RightType, RightField) \ class TraitsName\ {\ friend bd::bidi_ptr_left;\ friend bd::bidi_ptr_right;\ friend bd::bidi_ptr;\ friend bd::bidi_ptr;\ \ typedef class LeftType left_type;\ typedef class RightType right_type;\ \ template\ static void assign_2( left_type_* lhs, right_type_* rhs )\ {\ lhs->LeftField.ptr = rhs;\ rhs->RightField.ptr = lhs;\ }\ } //※ 無駄にassign_2がtemplateなのは、コンパイル時の依存関係を //※ 避けるためのdirty hackです。 } // namespace end //---------------------------------------------------------------------------- // 使い方 //---------------------------------------------------------------------------- using bd::bidi_ptr; // HeShe : Maleのshe と Femaleのhe は双方向関係です DEFINE_BIDI_PTR_TRAITS(HeShe, Male, she, Female, he); // WifeHusband : Maleのshe と Femaleのhe は双方向関係です DEFINE_BIDI_PTR_TRAITS(WifeHusband, Male, wife, Female, husband); // DaughterFather : FemaleのFather と Maleのdaughter は双方向関係です DEFINE_BIDI_PTR_TRAITS(DaughterFather, Female, father, Male, daughter); // Male / Female の定義 class Male; class Female; class Male { public: Male(const char* name) : name(name), she(this), wife(this), daughter(this) {} const char* name; bidi_ptr she; bidi_ptr wife; bidi_ptr daughter; }; class Female { public: Female(const char* name) : name(name), he(this), husband(this), father(this) {} const char* name; bidi_ptr he; bidi_ptr husband; bidi_ptr father; }; #include using namespace std; int main() { Male namihei("namihei"), masuo("masuo"); Female fune("fune"), sazae("sazae"); namihei.wife = &fune; namihei.daughter = &sazae; sazae.he = &masuo; cout << sazae.father->name << endl; // namihei cout << fune.husband->name << endl; // namihei cout << masuo.she->name << endl; // sazae }