/*! @file @brief 連結リストによる共有ポインタ - @ref _linked_ptr - @ref _slinked_ptr @author %Juna */ #ifndef Juna_LinkedList_SharedPointer_Hpp #define Juna_LinkedList_SharedPointer_Hpp #pragma warning( push ) #pragma warning( disable : 4355 ) //初期化時this使用警告の抑制 //! namespace Juna namespace Juna { //! デフォルト実装置き場 namespace linked_ptr_default { //! デフォルト単方向リスト接続子 class singly { singly(const singly &src); void operator=(const singly &src); protected: //! デフォルトコンストラクタ singly(void) : next(this) {} //! 非接続状態から、otherとの接続状態にする。 void connect(const singly &other) const { next = other.next; other.next = this; } //! 非接続状態にする。 void disconnect(void) const { const singly *p = next; while (p->next != this) p = p->next; p->next = next; next = this; } //! 接続数を数える long count(void) const { long count = 1; for (const singly *p = next;p->next != this;p = p->next) count++; return count; } //! 非接続状態かどうか bool unique(void) const {return next == this;} private: mutable const singly *next; }; //! デフォルト双方向リスト接続子 class doubly { doubly(const doubly &src); void operator=(const doubly &src); protected: //! デフォルトコンストラクタ doubly(void) : next(this),prev(this) {} //! 非接続状態から、otherとの接続状態にする。 void connect(const doubly &other) const { next = other.next; other.next = this; prev = &other; next->prev = this; } //! 非接続状態にする。 void disconnect(void) const { prev->next = next; next->prev = prev; next = prev = this; } //! 接続数を数える long count(void) const { long count = 1; for (const doubly *p = next;p->next != this;p = p->next) count++; return count; } //! 非接続状態かどうか bool unique(void) const {return next == this;} private: mutable const doubly *next; mutable const doubly *prev; }; //! デフォルトdelete削除子 struct delete_deleter { //! 削除実行 template void Delete(T *p) {delete p;} // pointerが0でも正しく動作しなければいけない delete_deleter(void) {} // コピーは異なるポインタ型に対する互換性のテストも兼ねる delete_deleter(const delete_deleter &) {} void operator=(const delete_deleter &) {} // 全て通してポインタの変換可能性に任せる }; // 削除子にメンバを持たせても構わないが、その分ポインタのサイズに追加される。 //! デフォルト配列delete削除子 template struct array_delete_deleter { //! 削除実行 void Delete(T *p) {delete[] p;} // 配列をポリモーフィックに扱うな、と // template // void array_deleter(const array_deleter &) {} }; }// namespace linked_ptr_default /*===========================================================================*/ //! @defgroup _linked_ptr //@{ //! (双方向)連結リストによる共有ポインタクラステンプレート /*! @param Deleter 削除子 @param Linker 接続子 */ template class linked_ptr : private Linker , private Deleter { protected: // void &除け // template struct linked_ptr_traits {typedef U & reference;}; // template<> struct linked_ptr_traits {typedef void reference;}; // typedef linked_ptr_traits::reference reference; // やっぱvoid禁止 typedef T value_type; typedef T& reference; typedef T* pointer; public: //! デフォルトコンストラクタ linked_ptr(Deleter &d = Deleter()) : Linker(),Deleter(d),Pointer(0) {} //! ポインタによるコンストラクタ explicit linked_ptr(pointer p,Deleter &d = Deleter()) : Linker(),Deleter(d),Pointer(p) {} //! 異種コピーコンストラクタ template explicit linked_ptr(const linked_ptr &src) : Linker(),Deleter(src.deleter()),Pointer(src.get()) {connect(src.linker());} //! コピーコンストラクタ linked_ptr(const linked_ptr &src) : Linker(),Deleter(src.deleter()),Pointer(src.get()) {connect(src.linker());} //! デストラクタ ~linked_ptr() {reset();} //! @name キャストコンストラクタタグ //@{ struct static_cast_tag {}; struct dynamic_cast_tag {}; //@} //! @name キャストコンストラクタ //@{ //! static_castコンストラクタ template linked_ptr(const linked_ptr &src,static_cast_tag) : Linker(),Deleter(src.deleter()),Pointer(static_cast(src.get())) {connect(src.linker());} //! dynamic_castコンストラクタ template linked_ptr(const linked_ptr &src,dynamic_cast_tag) : Linker(),Deleter(src.deleter()),Pointer(dynamic_cast(src.get())) { if (Pointer) connect(src.linker()); } //@} //! @name reset //@{ //! ポインタの解放 void reset(void) { if (unique()) deleter().Delete(Pointer); else disconnect(); Pointer = 0; } //! 新しいポインタの代入 template void reset(U *p,Deleter &d = Deleter()) { reset(); Pointer = p; deleter() = d; } //@} //! @name 参照 //@{ //! 直接参照 pointer get(void) const {return Pointer;} //! 参照外し reference operator*(void) const {return *get();} //! ->演算子 pointer operator->(void) const {return get();} //@} //! @name 代入演算子 //@{ //! 異種代入演算子 template linked_ptr &operator=(const linked_ptr &rhs) { if (get() == rhs.get()) return *this; reset(); Pointer = rhs.get(); connect(rhs.linker()); deleter() = rhs.deleter(); return *this; } //! 代入演算子 linked_ptr &operator=(const linked_ptr &rhs) { if (get() != rhs.get()) return *this; reset(); Pointer = rhs.get(); connect(rhs.linker()); deleter() = rhs.deleter(); return *this; } //@} // 下手に型変換が起こらない関数へのポインタを暗黙のブール型として使う、と // void *への代入が天敵 // typedef void (*unspecified_bool_type)(void); // まず型変換が起こらないメンバポインタを暗黙のブール型として使う typedef pointer (linked_ptr::*unspecified_bool_type)(void) const; //! @name bool //@{ //! bool operator unspecified_bool_type(void) const // {return reinterpret_cast(Pointer);} {return Pointer == 0 ? 0 : linked_ptr::get;} //! 単項!演算子 bool operator!(void) const {return Pointer == 0;} //@} //! @name 比較 //@{ //! ==演算子 template bool operator==(const linked_ptr &rhs) const {return Pointer == rhs.get();} //! !=演算子 template bool operator!=(const linked_ptr &rhs) const {return Pointer != rhs.get();} //@} //! @name 共有参照数 //@{ //! 参照数 /*! @return 自身の参照も含めた参照数(Nullへの参照時も1を返す) */ long use_count(void) const {return count();} //! 共有していないか /*! @retval true 共有していない @retval false 共有している */ bool unique(void) const {return Linker::unique();} //@} //! @name 実装インターフェイス //@{ //! 削除子 const Deleter &deleter(void) const {return *this;} //! 削除子 Deleter &deleter(void) {return *this;} //! 接続子 const Linker &linker(void) const {return *this;} //! 接続子 Linker &linker(void) {return *this;} //@} private: pointer Pointer; private: // 定義するつもりはなかったんだが、 // 何故か定義が無くてもコンパイルだけは通ってしまうので linked_ptr &operator=(pointer rhs) { reset(); Pointer = rhs; // 削除子は指定しようがないから引き継ぐ return *this; } }; //template class linked_ptr //! @name linked_ptrキャスト //@{ //! static_cast template linked_ptr static_pointer_cast(const linked_ptr &p) {return linked_ptr(p,linked_ptr::static_cast_tag());} //! dynamic_cast template linked_ptr dynamic_pointer_cast(const linked_ptr &p) {return linked_ptr(p,linked_ptr::dynamic_cast_tag());} //@} //@} group linked_ptr /*===========================================================================*/ //! @defgroup _slinked_ptr //@{ //! 単方向連結リストによる共有ポインタクラステンプレート /*! @sa Juna::linked_ptr */ template class slinked_ptr : public linked_ptr { typedef linked_ptr base_class; public: //! デフォルトコンストラクタ slinked_ptr(Deleter d = Deleter()) : base_class(d) {} //! ポインタによるコンストラクタ explicit slinked_ptr(pointer p,Deleter d = Deleter()) : base_class(p,d) {} //! 異種コピーコンストラクタ template explicit slinked_ptr(const slinked_ptr &src) : base_class(src) {} //! コピーコンストラクタ slinked_ptr(const slinked_ptr &src) : base_class(src) {} //!static_castコピーコンストラクタ template slinked_ptr(const linked_ptr &src,static_cast_tag dummy) : base_class(src,dummy) {} //dynamic_castコピーコンストラクタ template slinked_ptr(const slinked_ptr &src,dynamic_cast_tag dummy) : base_class(src,dummy) {} //! 異種代入演算子 template slinked_ptr &operator=(const slinked_ptr &rhs) {return base_class::operator=(rhs);} //! 代入演算子 slinked_ptr &operator=(const linked_ptr &rhs) {return base_class::operator=(rhs);} }; //! @name slinked_ptrキャスト //@{ //! static_cast template slinked_ptr static_pointer_cast(const slinked_ptr &p) {return slinked_ptr(p,linked_ptr::static_cast_tag());} //! dynamic_cast template slinked_ptr dynamic_pointer_cast(const slinked_ptr &p) {return slinked_ptr(p,linked_ptr::dynamic_cast_tag());} //@} //@} group slinked_ptr }//namespace Juna #pragma warning( pop ) #endif