From fcbdbfa9f6d2e8f1b9874764c40249010095487c Mon Sep 17 00:00:00 2001 From: Christian Engwer <christi@dune-project.org> Date: Sat, 27 Nov 2010 17:54:16 +0000 Subject: [PATCH] * add null_deleter to shared_ptr to handle stack objects * add two free functions for convient creation of a shared_ptr from a stack-allocated object [[Imported from SVN: r6273]] --- dune/common/shared_ptr.hh | 68 ++++++++++++++++++++++++++++++ dune/common/test/shared_ptrtest.cc | 20 +++++++++ 2 files changed, 88 insertions(+) diff --git a/dune/common/shared_ptr.hh b/dune/common/shared_ptr.hh index a3e590e9b..77059386a 100644 --- a/dune/common/shared_ptr.hh +++ b/dune/common/shared_ptr.hh @@ -17,6 +17,7 @@ #endif #include <dune/common/nullptr.hh> +#include <dune/common/typetraits.hh> /** * @file * @brief This file implements the class shared_ptr (a reference counting @@ -294,5 +295,72 @@ namespace Dune /** @} */ #endif // #ifdef SHARED_PTR_NAMESPACE + /** + @brief implements the Deleter concept of shared_ptr without deleting anything + @relates shared_ptr + + If you allocate an object on the stack, but want to pass it to a class or function as a shared_ptr, + you can use this deleter to avoid accidential deletion of the stack-allocated object. + + For convinience we provide two free functions to create a shared_ptr from a stack-allocated object + (\see stackobject_to_shared_ptr): + + 1) Convert a stack-allocated object to a shared_ptr: + @code + int i = 10; + shared_ptr<int> pi = stackobject_to_shared_ptr(i); + @endcode + 2) Convert a stack-allocated object to a shared_ptr of a base class + @code + class A {}; + class B : public A {}; + + ... + + B b; + shared_ptr<A> pa = stackobject_to_shared_ptr<A>(b); + @endcode + + @tparam T type of the stack-allocated object + */ + template<class T> + struct null_deleter + { + void operator() (T* p) const {} + }; + + /** + @brief Convert a stack-allocated object to a shared_ptr: + @relates shared_ptr + @code + int i = 10; + shared_ptr<int> pi = stackobject_to_shared_ptr(i); + @endcode + */ + template<typename T> + inline shared_ptr<T> stackobject_to_shared_ptr(T & t) + { + return shared_ptr<T>(&t, null_deleter<T>()); + } + + /** + @brief Convert a stack object to a shared_ptr of a base class + @relates shared_ptr + @code + class A {}; + class B : public A {}; + + ... + + B b; + shared_ptr<A> pa = stackobject_to_shared_ptr<A>(b); + @endcode + */ + template<typename T, typename T2> + inline shared_ptr<T2> stackobject_to_shared_ptr(T & t) + { + return shared_ptr<T2>(dynamic_cast<T2*>(&t), null_deleter<T2>()); + } + } #endif diff --git a/dune/common/test/shared_ptrtest.cc b/dune/common/test/shared_ptrtest.cc index 86b0473c4..79ea6ab1c 100644 --- a/dune/common/test/shared_ptrtest.cc +++ b/dune/common/test/shared_ptrtest.cc @@ -30,6 +30,10 @@ private: bool& deleted_; }; +class A {}; +class B : public A {}; +class C : A {}; + int main(){ using namespace Dune; int ret=0; @@ -154,6 +158,22 @@ int main(){ __FILE__<<std::endl; ret=1; } + + // test shared_ptr for stack allocation + { + int i = 10; + shared_ptr<int> pi = stackobject_to_shared_ptr(i); + } + + // test shared_ptr for stack allocation with down cast + { + B b; + shared_ptr<A> pa = stackobject_to_shared_ptr<A>(b); +#ifdef SHARED_PTR_COMPILE_FAIL + C c; + pa = stackobject_to_shared_ptr<A>(c); // A is an inaccessible base of C +#endif + } } return (ret); } -- GitLab