#ifndef Self_h__ #define Self_h__ #include namespace meow { /*! *@brief 具有copy on write, 且擁有比C++更靈活的reference機制 * *使用上就是把所有成員變數包到一個class/structure裡, 送給Self \n *例如以下 *@code{.cpp} * class A { * private: * struct Myself { * int data; * Myself(){ * data = 0; * } * ~Myself() { * } * Myself copyFrom(Myself const& ms) const { * data = ms.data; * } * }; * Self const self; * public: * A(): self(true) { // self(true) 表示要建立實體, 即struct Myself * } * A(A const& a): self(false) { // for std::swap * copyFrom(a); * } * // A(A const& a); // disable 模糊用法, 與上者二選一 * A(A const& a, bool reference): self(false) { * if (reference) { * referenceFrom(a); * } else { * copyFrom(a); * } * } * ~A() { * } * void setMemeber(int k) { * self()->data = k; // self()->?? 可以有write權限 * } * int getMemember(int wh) const { * return self->data; // self->?? 只有const * } * A referenceFrom(A const& a) { * self.referenceFrom(a.self); * } * A copyFrom(A const& a) { * self.copyFrom(a.self); * } * A& operator=(A const& b) { // for std::swap * copyFrom(b); * } * A& operator=(A const& b); // 避免諢亂用法 * }; * @endcode * *@author cathook * *@warning \c Self 這個class會把\c operator= 給disable掉, 所以使用它當 * kernel的class預設的 \c operator= 都會無法使用 */ template class Self { private: class Body { private: struct Kernel { Data data_; int counter_; Kernel() { counter_ = 1; } Kernel(Data const& data) { counter_ = 1; data_.copyFrom(data); } }; Kernel *pointer_; int counter_; public: Body() { counter_ = 1; pointer_ = new Kernel; } Body(Body const& b) { counter_ = 1; pointer_ = b.pointer_; pointer_->counter_++; } ~Body() { pointer_->counter_--; if (pointer_->counter_ <= 0) { delete pointer_; } } int attatch() { return ++counter_; } int detatch() { return --counter_; } Data const* access() const { return &(pointer_->data_); } Data * modify() { if (pointer_->counter_ > 1) { pointer_->counter_--; pointer_ = new Kernel(pointer_->data_); } return &(pointer_->data_); } }; Body* body_; void clear(Body* body) { if (body != NULL) { if (body->detatch() <= 0) { delete body; } } } public: /*! *@brief constructor * *@param [in] create_body 是否要new一個實體資料 (如果constructor完, 馬上就要 * \c copyFrom() , 或是 \c referenceFrom() 的話 * 不太需要 new一個實體, 否則基本上都要 */ Self(bool create_body) { body_ = (create_body ? new Body() : NULL); } //! @brief 不允許copy constructor Self(Self const& b); //! @brief 解構子 ~Self() { clear(body_); } //! @brief 回傳指向 Data const 的指標 Data const* operator->() const { return body_->access(); } //! @brief 回傳指向 Data 的指標, 如有需要, 這邊會做資料的duplicate Data* operator->() { return body_->modify(); } //! @brief 回傳非const型態的自己 Self& operator()() const { return *((Self*)this); } /*! *@brief 將給定的 \c Self 的資料複製到自己這裡 * *@param [in] s 給定的\c Self *@return 無 * *@note 與reference的差別是, copy之後若該給定的 \c Self 有資料修改, * this 這邊 \b 不會 被改到 */ void copyFrom(Self const& s) { Body* old = body_; body_ = new Body(*(s.body_)); clear(old); } /*! *@brief 將自己reference 到給定的 \c Self * *@param [in] s 給定的\c Self *@return 無 * *@note 把reference想像成指標會比較容易思考, 譬如 \c a.referenceFrom(b) * \c b.referenceFrom(c) 相當於 \b a指向b原本指的記憶體位置, * \b b指向c原本指的記憶體位置 , 之後更動c時, 只有b會被牽連 * */ void referenceFrom(Self const& s) { if (body_ != s.body_) { clear(body_); body_ = s.body_; body_->attatch(); } } /*! * @brief 比對兩個 \c Self 是否指向同一個reference * * @param [in] s 另一個 \c Self * @return \c true/false 表示是否為同一個reference */ bool same(Self const& s) const { return (body_ == s.body_); } /*! * @brief 比對兩個 \c Self 的內容是否一樣 * * @param [in] s 另一個 \c Self * @return \c true/false 表示兩個內容是否一樣 * * @note 需要用到 Data的equal() */ bool equal(Self const& s) const { if (same(s) || body_->access() == s.body_->access()) return true; return (body_->access()->equal(*(s.body_->access()))); } /*! * @brief 以reference作為判斷依據的小於判斷 * * @param [in] s 另一個 \c Self * @return \c true/false 表示自己是否小於另一個 \c Self */ bool referenceLess(Self const& s) const { return (body_ < s.body_); } //! @brief 將 \c operator= 給disable掉 void operator=(Self const& a); }; } // meow #endif // Self_h__