Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // AutoPtr.h
- //
- // $Id: //poco/1.4/Foundation/include/Poco/AutoPtr.h#1 $
- //
- // Library: Foundation
- // Package: Core
- // Module: AutoPtr
- //
- // Definition of the AutoPtr template class.
- //
- // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
- // and Contributors.
- //
- // Permission is hereby granted, free of charge, to any person or organization
- // obtaining a copy of the software and accompanying documentation covered by
- // this license (the "Software") to use, reproduce, display, distribute,
- // execute, and transmit the Software, and to prepare derivative works of the
- // Software, and to permit third-parties to whom the Software is furnished to
- // do so, all subject to the following:
- //
- // The copyright notices in the Software and this entire statement, including
- // the above license grant, this restriction and the following disclaimer,
- // must be included in all copies of the Software, in whole or in part, and
- // all derivative works of the Software, unless such copies or derivative
- // works are solely in the form of machine-executable object code generated by
- // a source language processor.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
- // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
- // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
- // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- // DEALINGS IN THE SOFTWARE.
- //
- #ifndef Foundation_AutoPtr_INCLUDED
- #define Foundation_AutoPtr_INCLUDED
- #include "Poco/Foundation.h"
- #include "Poco/Exception.h"
- #include <algorithm>
- #include <functional> // for std::less, greater, etc
- namespace Poco {
- template <class C>
- class AutoPtr
- /// AutoPtr is a "smart" pointer for classes implementing
- /// reference counting based garbage collection.
- /// To be usable with the AutoPtr template, a class must
- /// implement the following behaviour:
- /// A class must maintain a reference count.
- /// The constructors of the object initialize the reference
- /// count to one.
- /// The class must implement a public duplicate() method:
- /// void duplicate();
- /// that increments the reference count by one.
- /// The class must implement a public release() method:
- /// void release()
- /// that decrements the reference count by one, and,
- /// if the reference count reaches zero, deletes the
- /// object.
- ///
- /// AutoPtr works in the following way:
- /// If an AutoPtr is assigned an ordinary pointer to
- /// an object (via the constructor or the assignment operator),
- /// it takes ownership of the object and the object's reference
- /// count remains unchanged.
- /// If the AutoPtr is assigned another AutoPtr, the
- /// object's reference count is incremented by one by
- /// calling duplicate() on its object.
- /// The destructor of AutoPtr calls release() on its
- /// object.
- /// AutoPtr supports dereferencing with both the ->
- /// and the * operator. An attempt to dereference a null
- /// AutoPtr results in a NullPointerException being thrown.
- /// AutoPtr also implements all relational operators.
- /// Note that AutoPtr allows casting of its encapsulated data types.
- {
- public:
- AutoPtr(): _ptr(0)
- {
- }
- AutoPtr(C* ptr): _ptr(ptr)
- {
- }
- AutoPtr(C* ptr, bool shared): _ptr(ptr)
- {
- if (shared && _ptr) _ptr->duplicate();
- }
- AutoPtr(const AutoPtr& ptr): _ptr(ptr._ptr)
- {
- if (_ptr) _ptr->duplicate();
- }
- template <class Other>
- AutoPtr(const AutoPtr<Other>& ptr): _ptr(ptr.get())
- {
- if (_ptr) _ptr->duplicate();
- }
- ~AutoPtr()
- {
- if (_ptr) _ptr->release();
- }
- AutoPtr& assign(C* ptr)
- {
- if (_ptr != ptr)
- {
- if (_ptr) _ptr->release();
- _ptr = ptr;
- }
- return *this;
- }
- AutoPtr& assign(C* ptr, bool shared)
- {
- if (_ptr != ptr)
- {
- if (_ptr) _ptr->release();
- _ptr = ptr;
- if (shared && _ptr) _ptr->duplicate();
- }
- return *this;
- }
- AutoPtr& assign(const AutoPtr& ptr)
- {
- if (&ptr != this)
- {
- if (_ptr) _ptr->release();
- _ptr = ptr._ptr;
- if (_ptr) _ptr->duplicate();
- }
- return *this;
- }
- template <class Other>
- AutoPtr& assign(const AutoPtr<Other>& ptr)
- {
- if (ptr.get() != _ptr)
- {
- if (_ptr) _ptr->release();
- _ptr = ptr.get();
- if (_ptr) _ptr->duplicate();
- }
- return *this;
- }
- AutoPtr& operator = (C* ptr)
- {
- return assign(ptr);
- }
- AutoPtr& operator = (const AutoPtr& ptr)
- {
- return assign(ptr);
- }
- template <class Other>
- AutoPtr& operator = (const AutoPtr<Other>& ptr)
- {
- return assign<Other>(ptr);
- }
- void swap(AutoPtr& ptr)
- {
- std::swap(_ptr, ptr._ptr);
- }
- template <class Other>
- AutoPtr<Other> cast() const
- /// Casts the AutoPtr via a dynamic cast to the given type.
- /// Returns an AutoPtr containing NULL if the cast fails.
- /// Example: (assume class Sub: public Super)
- /// AutoPtr<Super> super(new Sub());
- /// AutoPtr<Sub> sub = super.cast<Sub>();
- /// poco_assert (sub.get());
- {
- Other* pOther = dynamic_cast<Other*>(_ptr);
- return AutoPtr<Other>(pOther, true);
- }
- template <class Other>
- AutoPtr<Other> unsafeCast() const
- /// Casts the AutoPtr via a static cast to the given type.
- /// Example: (assume class Sub: public Super)
- /// AutoPtr<Super> super(new Sub());
- /// AutoPtr<Sub> sub = super.unsafeCast<Sub>();
- /// poco_assert (sub.get());
- {
- Other* pOther = static_cast<Other*>(_ptr);
- return AutoPtr<Other>(pOther, true);
- }
- C* operator -> () const
- {
- if (_ptr)
- return _ptr;
- else
- throw NullPointerException();
- }
- C& operator * () const
- {
- if (_ptr)
- return *_ptr;
- else
- throw NullPointerException();
- }
- C* get() const
- {
- return _ptr;
- }
- // This also serves as an safe implicit conversion to a boolean type
- operator C* () const
- {
- return _ptr;
- }
- bool operator ! () const
- {
- return _ptr == 0;
- }
- bool isNull() const
- {
- return _ptr == 0;
- }
- C* duplicate() const
- {
- if (_ptr) _ptr->duplicate();
- return _ptr;
- }
- private:
- C* _ptr;
- };
- namespace Detail {
- // This class will generate a compilation error if the types T and U
- // can not be compared, i.e. they do not have a a composite
- // pointer type
- // Intentionaly complex to reduce the likeliness of warnings
- template <class T, class U>
- struct EnsureHasCompositePointerType
- {
- static void constraints(T* a, U* b, bool& x)
- {
- // If you get a compilation error here, then you have
- // tried to compare two smart pointers with
- // unrelated types.
- x = a < b;
- }
- typedef void f_type(T*, U*, bool&);
- void no_op(f_type)
- {
- // empty on purpose
- }
- EnsureHasCompositePointerType()
- {
- // This assignment should be optimized away by the compiler
- void (*p)(T*, U*, bool&) = constraints;
- // To get rid of the warning that we do not use the
- // variable
- no_op(p);
- }
- };
- // The use of EnsureHasCompositePointerType, is done to ensure that
- // the pointers can be compared using the normal C++ language rules.
- // The reason the operators are not used directly is because
- // they are not required to give a total ordering for objects of any
- // type, however the predicates, eg. std::less, are required to give
- // a total ordering.
- template <class T, class U>
- bool pointerLess(T* a, U* b)
- {
- EnsureHasCompositePointerType<T, U>();
- return std::less<const void*>()(a, b);
- }
- template <class T, class U>
- bool pointerLessEq(T* a, U* b)
- {
- EnsureHasCompositePointerType<T, U>();
- return std::less_equal<const void*>()(a, b);
- }
- template <class T, class U>
- bool pointerGreater(T* a, U* b)
- {
- EnsureHasCompositePointerType<T, U>();
- return std::greater<const void*>()(a, b);
- }
- template <class T, class U>
- bool pointerGreaterEq(T* a, U* b)
- {
- EnsureHasCompositePointerType<T, U>();
- return std::greater_equal<const void*>()(a, b);
- }
- }
- template <class C>
- inline void swap(AutoPtr<C>& p1, AutoPtr<C>& p2)
- {
- p1.swap(p2);
- }
- template <class T, class U>
- bool operator == (const AutoPtr<T>& a, const AutoPtr<U>& b)
- {
- return a.get() == b.get();
- }
- template <class T, class U>
- bool operator == (T* a, const AutoPtr<U>& b)
- {
- return a == b.get();
- }
- template <class T, class U>
- bool operator == (const AutoPtr<T>& a, U* b)
- {
- return a.get() == b;
- }
- template <class T, class U>
- bool operator != (const AutoPtr<T>& a, const AutoPtr<U>& b)
- {
- return a.get() != b.get();
- }
- template <class T, class U>
- bool operator != (T* a, const AutoPtr<U>& b)
- {
- return a != b.get();
- }
- template <class T, class U>
- bool operator != (const AutoPtr<T>& a, U* b)
- {
- return a.get() != b;
- }
- template <class T, class U>
- bool operator < (const AutoPtr<T>& a, const AutoPtr<U>& b)
- {
- return Detail::pointerLess(a.get(), b.get());
- }
- template <class T, class U>
- bool operator < (T* a, const AutoPtr<U>& b)
- {
- return Detail::pointerLess(a, b.get());
- }
- template <class T, class U>
- bool operator < (const AutoPtr<T>& a, U* b)
- {
- return Detail::pointerLess(a.get(), b);
- }
- template <class T, class U>
- bool operator <= (const AutoPtr<T>& a, const AutoPtr<U>& b)
- {
- return Detail::pointerLessEq(a.get(), b.get());
- }
- template <class T, class U>
- bool operator <= (T* a, const AutoPtr<U>& b)
- {
- return Detail::pointerLessEq(a, b.get());
- }
- template <class T, class U>
- bool operator <= (const AutoPtr<T>& a, U* b)
- {
- return Detail::pointerLessEq(a.get(), b);
- }
- template <class T, class U>
- bool operator > (const AutoPtr<T>& a, const AutoPtr<U>& b)
- {
- return Detail::pointerGreater(a.get(), b.get());
- }
- template <class T, class U>
- bool operator > (T* a, const AutoPtr<U>& b)
- {
- return Detail::pointerGreater(a, b.get());
- }
- template <class T, class U>
- bool operator > (const AutoPtr<T>& a, U* b)
- {
- return Detail::pointerGreater(a.get(), b);
- }
- template <class T, class U>
- bool operator >= (const AutoPtr<T>& a, const AutoPtr<U>& b)
- {
- return Detail::pointerGreaterEq(a.get(), b.get());
- }
- template <class T, class U>
- bool operator >= (T* a, const AutoPtr<U>& b)
- {
- return Detail::pointerGreaterEq(a, b.get());
- }
- template <class T, class U>
- bool operator >= (const AutoPtr<T>& a, U* b)
- {
- return Detail::pointerGreaterEq(a.get(), b);
- }
- } // namespace Poco
- #endif // Foundation_AutoPtr_INCLUDED
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement