Help with shared_ptr usage?

Hi, I can need some help with getting similar behavior as with shared_ptr for my classes., I have used std::shared_ptr with C++0x which matches the boost support. I have two classes, Base and Derived. Now I want to give our users not directly access to these implementation classes, but to some reference to them. I have created two templates, BaseRef_T and Derived_objref (see below). In Derived_objref I need to add some additional typedefs and type definitions. I have tried first to add these typedefs to a specialization of shared_ptr<> but couldn't get a clean solution. If I now use shared_ptr I can take a shared_ptr for a Derived and assign it to a BaseRef_T. That works without problems. But how to accomplish this with my own wrapper classes. This should only be possible when the types are related to inheritance. If I have now a D that is not derived from Base than that shouldn't work. Johnny #include <memory> class Base { public: }; class Derived : public virtual Base { public: }; template <typename T> class BaseRef_T { public: BaseRef_T (std::shared_ptr <T> t) : impl_ (t) {}; BaseRef_T (T* t) : impl_ (t) {}; BaseRef_T (void) : impl_ () {}; typedef T element_type; inline T* operator-> () { return impl_.get ();} inline T* get() const { return impl_.get ();} explicit operator bool() const // never throws { return impl_ == 0 ? false : true; } void operator=(const std::nullptr_t& t) // never throws { impl_ = t; } // protected: typedef std::shared_ptr <T> shared_ptr_type; shared_ptr_type impl_; }; typedef BaseRef_T <Base> BaseRef; template <typename T> class Derived_objref : public virtual BaseRef_T <T> { public: Derived_objref () : BaseRef_T<T> () {} Derived_objref (T *s) : BaseRef_T<T> (s) {} Derived_objref (const BaseRef_T <T>& o) : BaseRef_T <T> (o) {} void operator=(const std::nullptr_t& t) { this->impl_ = t; } typedef int my_index_type; // Needed as additional typedef for Derived struct Foo {int a;}; }; typedef Derived_objref <Derived> DerivedRef; int main (int,char*[]) { std::shared_ptr<Base> bs (new Base); std::shared_ptr<Derived> ds (new Derived); std::shared_ptr<Base> cs = ds; BaseRef b (new Base); DerivedRef d(new Derived); BaseRef c = d; // <== how to get this working? return 0; }

Hi Johnny, Sound like the type coercion you are trying to achieve can be done using templatized constructor and a templatized copy assignment operator. I would first start with the Coercion by member template idiom here: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Coercion_by_Member_Template Looks like you using C++0x. So you may also want to throw in a static_assert that checks the inheritance relationship between type parameters using boost::is_base_of<T1, T2> Code below tested on g++4.6 seems to work on your program. template<class T> class BaseRef_T { template <class U> BaseRef_T (const BaseRef_T<U> & baseu): impl_(baseu.impl_) { static_assert(std::is_base_of<T, U>::value, "T is not base of U"); } template <class U> BaseRef_T & operator = (const BaseRef_T<U> & baseu) { static_assert(std::is_base_of<T, U>::value, "T is not base of U"); this->impl_=baseu.impl_; return *this; } }; Finally, you may want to ask questions like these on stackoverflow where responses are quicker and the right answer gets upvotes overtime increasing confidence in it. Sumant On 3 June 2011 01:20, Johnny Willemsen <jwillemsen@remedy.nl> wrote:
Hi,
I can need some help with getting similar behavior as with shared_ptr for my classes., I have used std::shared_ptr with C++0x which matches the boost support.
I have two classes, Base and Derived. Now I want to give our users not directly access to these implementation classes, but to some reference to them. I have created two templates, BaseRef_T and Derived_objref (see below). In Derived_objref I need to add some additional typedefs and type definitions. I have tried first to add these typedefs to a specialization of shared_ptr<> but couldn't get a clean solution.
If I now use shared_ptr I can take a shared_ptr for a Derived and assign it to a BaseRef_T. That works without problems. But how to accomplish this with my own wrapper classes. This should only be possible when the types are related to inheritance. If I have now a D that is not derived from Base than that shouldn't work.
Johnny
#include <memory>
class Base { public: };
class Derived : public virtual Base { public: };
template <typename T> class BaseRef_T { public: BaseRef_T (std::shared_ptr <T> t) : impl_ (t) {}; BaseRef_T (T* t) : impl_ (t) {}; BaseRef_T (void) : impl_ () {}; typedef T element_type; inline T* operator-> () { return impl_.get ();} inline T* get() const { return impl_.get ();} explicit operator bool() const // never throws { return impl_ == 0 ? false : true; } void operator=(const std::nullptr_t& t) // never throws { impl_ = t; }
// protected: typedef std::shared_ptr <T> shared_ptr_type; shared_ptr_type impl_; }; typedef BaseRef_T <Base> BaseRef;
template <typename T> class Derived_objref : public virtual BaseRef_T <T> { public: Derived_objref () : BaseRef_T<T> () {} Derived_objref (T *s) : BaseRef_T<T> (s) {} Derived_objref (const BaseRef_T <T>& o) : BaseRef_T <T> (o) {} void operator=(const std::nullptr_t& t) { this->impl_ = t; } typedef int my_index_type; // Needed as additional typedef for Derived struct Foo {int a;}; }; typedef Derived_objref <Derived> DerivedRef;
int main (int,char*[]) { std::shared_ptr<Base> bs (new Base); std::shared_ptr<Derived> ds (new Derived); std::shared_ptr<Base> cs = ds; BaseRef b (new Base); DerivedRef d(new Derived); BaseRef c = d; // <== how to get this working? return 0; }
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- int main(void) { while(1) KeepWorking(); }
participants (2)
-
Johnny Willemsen
-
Sumant Tambe