diff options
author | cathook <b01902109@csie.ntu.edu.tw> | 2014-06-01 13:56:57 +0800 |
---|---|---|
committer | cathook <b01902109@csie.ntu.edu.tw> | 2014-06-01 13:56:57 +0800 |
commit | d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0 (patch) | |
tree | 16f7920c5079e0aefcf9509d2dbab59c464d42bd /meowpp/Self.h | |
parent | bd58f63900410ec4764031f2e6de2d75e91434b3 (diff) | |
download | meow-d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0.tar.gz meow-d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0.tar.zst meow-d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0.zip |
big chnage
Diffstat (limited to 'meowpp/Self.h')
-rw-r--r-- | meowpp/Self.h | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/meowpp/Self.h b/meowpp/Self.h new file mode 100644 index 0000000..5a62984 --- /dev/null +++ b/meowpp/Self.h @@ -0,0 +1,230 @@ +#ifndef Self_h__ +#define Self_h__ + +#include <cstdlib> + +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<Myself> 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 Data> +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__ |