// (C) Porkolab 2003 // // A.5.11. // // Value pointer class // // ValuePtr without copy and assignment template <typename T> class ValuPtr { public: explicit ValuePtr(T *p = 0) : p_(p) { } ~ValuePtr() { delete p_; } T& operator*() const { return *p_; } T* operator->() const { return p_; } vod Swap( ValuePtr& other) { swap(p_, other.p_); } private: T *p; // no copy ValuePtr(const ValuePtr&); ValuePtr& operator=(const ValuePtr&); }; ///////////////////////////////////////////////////////// // ValuePtr with copy and assignment template <typename T> class ValuPtr { public: explicit ValuePtr(T *p = 0) : p_(p) { } ~ValuePtr() { delete p_; } T& operator*() const { return *p_; } T* operator->() const { return p_; } ValuePtr(const ValuePtr&) : p_(other.p ? new T(*other.p_) : 0) {} ValuePtr& operator=(const ValuePtr&) { ValuePtr temp(other); Swap(temp); return *this; } vod Swap( ValuePtr& other) { swap(p_, other.p_); } private: T *p; }; ////////////////////////////////////////////////////// // ValuePtr with copy and assignment // and template versions for assigning different types template <typename T> class ValuPtr { public: explicit ValuePtr(T *p = 0) : p_(p) { } ~ValuePtr() { delete p_; } T& operator*() const { return *p_; } T* operator->() const { return p_; } ValuePtr(const ValuePtr&) : p_(other.p ? new T(*other.p_) : 0) {} ValuePtr& operator=(const ValuePtr&) { ValuePtr temp(other); Swap(temp); return *this; } template <typename U> ValuePtr(const ValuePtr<U>&) : p_(other.p ? new T(*other.p_) : 0) {} template <typename U> ValuePtr& operator=(const ValuePtr<U>&) { ValuePtr temp(other); Swap(temp); return *this; } vod Swap( ValuePtr& other) { swap(p_, other.p_); } private: template <typename U> friend class ValuePtr; T *p; }; // small problem: slicing class A {}; class B : public A {}; class C : public B {}; ValuePtr<A> a1(new B); ValuePtr<B> a1(new C); ValuePtr<A> a2(a1); // copy ctr: slicing ValuePtr<A> a3(b1); // templated constructor: slicing a2 = a1; // copy assignment: slicing a3 = b1; // templated constructor, slicing /////////////////////////////////////////////////////////////// // ValuePtr with copy and assignment // with virtual clone() method or with copy constructor template <typename T> class VPTraits { static T* Clone(const T* p) { return new T(*p); } }; template <typename T> class ValuPtr { public: explicit ValuePtr(T *p = 0) : p_(p) { } ~ValuePtr() { delete p_; } T& operator*() const { return *p_; } T* operator->() const { return p_; } ValuePtr(const ValuePtr&) : p_( CreateFrom(other.p_) ) {} ValuePtr& operator=(const ValuePtr&) { ValuePtr temp(other); Swap(temp); return *this; } template <typename U> ValuePtr(const ValuePtr<U>&) : p_( CreateFrom(other.p_) ) {} template <typename U> ValuePtr& operator=(const ValuePtr<U>&) { ValuePtr temp(other); Swap(temp); return *this; } vod Swap( ValuePtr& other) { swap(p_, other.p_); } private: template <typename U> friend class ValuePtr; template <typename U> T* CreateFrom(const U* p) const { return p ? VPTraits<U>::Clone() : 0; } T *p; }; // alternative solution template<typename T, typename Traits = VPTraits<T> > class ValuePtr { /* ...*/ };