diff --git a/dune/common/shared_ptr.hh b/dune/common/shared_ptr.hh index a6b99b6b0a7826112cfa3babc37a111c92e28f4b..58fe766b94b56aa87f14b374284a72535d9db8e7 100644 --- a/dune/common/shared_ptr.hh +++ b/dune/common/shared_ptr.hh @@ -43,6 +43,8 @@ namespace Dune template<class T> class shared_ptr { + template<class T1> friend class shared_ptr; + public: /** * @brief The data type we are a pointer for. @@ -64,7 +66,8 @@ namespace Dune * note: the object must be allocated on the heap and after handing the pointer to * shared_ptr the ownership of the pointer is also handed to the shared_ptr. */ - inline shared_ptr(T * pointer); + template<class T1> + inline shared_ptr(T1 * pointer); /** * @brief Constructs a new smart pointer from a preallocated Object. @@ -78,14 +81,15 @@ namespace Dune * note: the object must be allocated on the heap and after handing the pointer to * shared_ptr the ownership of the pointer is also handed to the shared_ptr. */ - template<class Deleter> - inline shared_ptr(T * pointer, Deleter deleter); + template<class T1, class Deleter> + inline shared_ptr(T1 * pointer, Deleter deleter); /** * @brief Copy constructor. * @param pointer The object to copy. */ - inline shared_ptr(const shared_ptr<T>& pointer); + template<class T1> + inline shared_ptr(const shared_ptr<T1>& pointer); /** * @brief Destructor. @@ -93,7 +97,8 @@ namespace Dune inline ~shared_ptr(); /** \brief Assignment operator */ - inline shared_ptr& operator=(const shared_ptr<T>& pointer); + template<class T1> + inline shared_ptr& operator=(const shared_ptr<T1>& pointer); /** \brief Dereference as object */ inline element_type& operator*(); @@ -121,11 +126,12 @@ namespace Dune inline void reset(); /** \brief Detach shared pointer and set it anew for the given pointer */ - inline void reset(T* pointer); + template<class T1> + inline void reset(T1* pointer); //** \brief Same as shared_ptr(pointer,deleter).swap(*this) - template<class Deleter> - inline void reset(T* pointer, Deleter deleter); + template<class T1, class Deleter> + inline void reset(T1* pointer, Deleter deleter); /** \brief The number of shared_ptrs pointing to the object we point to */ int use_count() const; @@ -134,14 +140,27 @@ namespace Dune /** @brief The object we reference. */ class PointerRep { - friend class shared_ptr<element_type>; + template<class T1> + friend class shared_ptr; protected: /** @brief The number of references. */ int count_; /** @brief The representative. */ element_type * rep_; /** @brief Constructor from existing Pointer. */ - PointerRep(element_type * p) : count_(1), rep_(p) {} + template<class T1> + PointerRep(T1 * p) : count_(1), rep_(p) {} + /** @brief Copy constructor with type conversion. */ + template<class T1> + PointerRep(const typename shared_ptr<T1>::PointerRep& rep) + : count_(rep.count_), rep_(rep.rep_) {} + + template<class T1> + operator typename shared_ptr<T1>::PointerRep() + { + return shared_ptr<T1>::PointerRep(*this); + } + /** @brief Destructor, deletes element_type* rep_. */ virtual ~PointerRep() {}; }; @@ -151,14 +170,17 @@ namespace Dune class PointerRepImpl : public PointerRep { - friend class shared_ptr<element_type>; - + template<class T1> + friend class shared_ptr; /** @brief Constructor from existing Pointer with custom deleter. */ PointerRepImpl(element_type * p, const Deleter& deleter) : PointerRep(p), deleter_(deleter) {} - + /** @brief Copy constructor with type conversion. */ + template<class T1> + PointerRepImpl(const typename shared_ptr<T1>::PointerRepImpl& rep) + : PointerRep(rep), deleter_(rep.deleter_) {} /** @brief Destructor, deletes element_type* rep_ using deleter. */ ~PointerRepImpl() { deleter_(this->rep_); } @@ -191,14 +213,15 @@ namespace Dune }; template<class T> - inline shared_ptr<T>::shared_ptr(T * p) + template<class T1> + inline shared_ptr<T>::shared_ptr(T1 * p) { rep_ = new PointerRepImpl<DefaultDeleter>(p, DefaultDeleter()); } template<class T> - template<class Deleter> - inline shared_ptr<T>::shared_ptr(T * p, Deleter deleter) + template<class T1, class Deleter> + inline shared_ptr<T>::shared_ptr(T1 * p, Deleter deleter) { rep_ = new PointerRepImpl<Deleter>(p, deleter); } @@ -210,14 +233,18 @@ namespace Dune } template<class T> - inline shared_ptr<T>::shared_ptr(const shared_ptr<T>& other) : rep_(other.rep_) + template<class T1> + inline shared_ptr<T>::shared_ptr(const shared_ptr<T1>& other) : rep_() { + rep_->count_=other.rep_->count_; + rep_->rep_=other.rep_->rep_; if (rep_) ++(rep_->count_); } template<class T> - inline shared_ptr<T>& shared_ptr<T>::operator=(const shared_ptr<T>& other) + template<class T1> + inline shared_ptr<T>& shared_ptr<T>::operator=(const shared_ptr<T1>& other) { if (other.rep_) (other.rep_->count_)++; @@ -283,14 +310,15 @@ namespace Dune } template<class T> - inline void shared_ptr<T>::reset(T* pointer) + template<class T1> + inline void shared_ptr<T>::reset(T1* pointer) { shared_ptr<T>(pointer).swap(*this); } template<class T> - template<class Deleter> - inline void shared_ptr<T>::reset(T* pointer, Deleter deleter) + template<class T1, class Deleter> + inline void shared_ptr<T>::reset(T1* pointer, Deleter deleter) { shared_ptr<T>(pointer, deleter).swap(*this); } diff --git a/dune/common/test/shared_ptrtest.cc b/dune/common/test/shared_ptrtest.cc index 921a353a6ced2c536612faa618f27de45d9a87c9..daddbe57d67c0a18f9c259f6e8eb91e9eb8d9f18 100644 --- a/dune/common/test/shared_ptrtest.cc +++ b/dune/common/test/shared_ptrtest.cc @@ -14,6 +14,7 @@ #if defined(DISABLE_CONFIGURED_SHARED_PTR) && defined(SHARED_PTR_NAMESPACE) #undef SHARED_PTR_NAMESPACE +#undef HAVE_MAKE_SHARED #endif #include <dune/common/classname.hh> @@ -47,6 +48,13 @@ class A {}; class B : public A {}; class C : A {}; + +Dune::shared_ptr<A> test_make_shared() +{ + return Dune::make_shared<B>(); +} + + int main(){ using namespace Dune; int ret=0; @@ -54,6 +62,9 @@ int main(){ // test default constructor shared_ptr<int> foo; + // test conversion in make_shared + shared_ptr<A> a=test_make_shared(); + // print the type of the shared_ptr, so we know whether we are // checking dune's shared_ptr or some std one std::cout << "=== checking shared_ptr type: " << className(foo)