diff --git a/dune/common/shared_ptr.hh b/dune/common/shared_ptr.hh index a3e590e9b9e2bc667f06cd7f748962e3493c8d92..77059386a9ab8d413b2266db1653e8244da9ae7e 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 86b0473c4dbd744152472610aaa7d712ece8cde9..79ea6ab1ce6eef611616d3911b738b1b6c0f4fbc 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); }