#ifndef Self_h__ #define Self_h__ #include namespace meow { /*! *@brief A little class use for packing the data part of another class. * With this technique, it can achieve Copy-On-Write(COR) mechanism at * background and have a reference mechanism which much more flexible * then the one C++ has. * * Sample code: *@code{.cpp} * class A { * private: * struct Myself { * int data; * * Myself() { // Necessary * data = 0; * } * * Myself(Myself const& b): data(b.data) { // Necessary, copy constructor * } * * ~Myself() { * } * * bool operator==(Myself const& b) const { // Optional (this method will * // be called only if you use * // Self::equal() method) * return (data == b.data); * } * }; * * Self const self; // Here we use 'constant' data type in * // order to have a coutious coding style * // and allow the COR mechanism to clone * // data only when we really want to * // modify them. * public: * A(): self() { } // Default constructor * * A(A const& a): self(a.self, COPY_FROM) { } // Copy constructor. You must * // tell me which way of * // duplicating should I use. * // It strongly recommended you * // use COYP_FROM for keeping the * // C++'s original behavior. * ~A() { } * * int getMemember(int wh) const { * return self->data; // Use 'operator->()' to get the pointer of the data * // The pointer is constant or not will depend on * // whether the left side variable of '->' is * // constant or not. * // If we just want to read the data, use * // 'self' instead of 'self()' * } * void setMemeber(int k) { * self()->data = k; // As a result of 'self()' returning a non-constant * // reference of itself, here we get the permission * // for modiying data. * // So now we can observe that if you type * // 'Self self' instead of the one above, * // 'self' and 'self()' will become the same one and * // both of them allow you using '->' for getting * // writing permission. At the same time, the COR * // machanism will become useless because everytime * // you want to access the date, Self will copy the * // data to prevent you to modify it no matter that * // you might just want to read it. * } * * A referenceFrom(A const& a) { * self.referenceFrom(a.self); * } * * A copyFrom(A const& a) { * self.copyFrom(a.self); * } * * A& operator=(A const& b) { // If you really like to use operator=, it * // strongly recommended you use 'copyFrom()' for * // keeping C++'s original behavior. * copyFrom(b); * } * }; *@endcode * Note that 'referenceFrom()' will cause the two object become the same one, * Which means that if you do something like '\c a.referenceFrom(b); * \c a.copyFrom(c); ', the result is that the value of \c a,b,c will all the * same one. * *@author cathook * *@warning This class disabled the method \c operator= and copy constructor * in order to prevent upexplicit default behavior, so if you want * to have one of them (or both), you must implement yourself */ template class Self { public: /*! * @brief Kind of ways of duplicating */ enum DuplicateType { COPY_FROM, //!< Normal copy operation REFERENCE_FROM //!< By reference, much like pointer's copy operation }; private: class Body { private: struct Kernel { Data data_; int counter_; Kernel( ): data_( ), counter_(1) { } Kernel(Data const& data): data_(data), counter_(1) { } ~Kernel() { } }; Kernel* pointer_; int counter_; public: Body( ): pointer_(new Kernel( )), counter_(1) { } Body(Data const& d): pointer_(new Kernel(d)), counter_(1) { } Body(Body const& b): pointer_(b.pointer_ ), counter_(1) { ++pointer_->counter_; } ~Body() { clear(); } Body& copyFrom(Body const& b) { clear(); pointer_ = b.pointer_; ++(pointer_->counter_); return *this; } void clear() { --(pointer_->counter_); if (pointer_->counter_ <= 0) { delete pointer_; } } int attach() { return ++counter_; } int detach() { 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() { if (body_->detach() <= 0) { delete body_; } } public: /*! * @brief constructor with a real entity */ Self(): body_(new Body()) { } /*! * @brief connstructor with a real entity with it using its copy constructor * * @param [in] d Inital data */ Self(Data const& d): body_(new Body(d)) { } /*! * @brief constructor with given another Self * * @param [in] b Another Self object. * @param [in] d To indicate type of way of duplicating */ Self(Self const& b, DuplicateType d) { switch(d) { case COPY_FROM: body_ = new Body(*b.body_); break; case REFERENCE_FROM: body_ = b.body_; body_->attach(); break; } } //! @brief Disallow copy constructor Self(Self const& b); //! @brief destructor ~Self() { clear(); } //! @brief Return the constant pointer to the data Data const* operator->() const { return body_->access(); } /*! @brief Return the non-constant pointer to the data (COR's clone might * occure here. */ Data* operator->() { return body_->modify(); } //! @brief Return the non-constant reference of \c *this Self& operator()() const { return *((Self*)this); } /*! * @brief Copy the gived \c Self to myself * * @param [in] s gived \c Self * @return *this */ Self const& copyFrom(Self const& s) { if (body_->access() != s.body_->access()) { body_->copyFrom(*s.body_); } return *this; } /*! * @brief Reference myself from given \c Self object. * * @param [in] s given \c Self * @return *this */ Self const& referenceFrom(Self const& s) { if (body_ != s.body_) { clear(); body_ = s.body_; body_->attach(); } return *this; } /*! * @brief call \c copyFrom() or \c referenceFrom() depend on your instruction * * @param [in] s gived \c Self object * @param [in] t instruction * @return *this */ Self const& duplicateFrom(Self const& s, DuplicateType t) { switch(t) { case COPY_FROM : return copyFrom(s); case REFERENCE_FROM: return referenceFrom(s); } return *this; } /*! * @brief Compare tht if the gived \c Self object is reference from the same * object of me * * @param [in] s gived \c Self object * @return \c true if we are referenced to the same object. */ bool same(Self const& s) const { return (body_ == s.body_); } /*! * @brief Compare that the data are the same. * * @param [in] s another \c Self object * @return \c true if the data are same. * * @note This will need the method 'Data::equal()' */ bool equal(Self const& s) const { if (same(s) || body_->access() == s.body_->access()) return true; return (*body_->access() == *s.body_->access()); } /*! * @brief Order compare by reference pointer. * * @param [in] s another \c Self object */ bool referenceLess(Self const& s) const { return (body_ < s.body_); } //! @brief Disallow default \c 'operator=' void operator=(Self const& a); }; } // meow #endif // Self_h__