subclassing shared_ptr?
- I'm porting to C++ a huge java library.
- Java constructor semantics is close to that of C++ but not identical.
- boost::shared_ptr does nearly exactly what I want except for
1 little thing peculiar to the project I'm working on.
The short story is that, for the C++ version, I need an "after ctor"
method to be called before any other member function is allowed
to be called. The logical next step was to override operator->
which led me to a long route ending now with boost::shared_ptr.
I should be able to solve my problem by _patching_ my local copy of
shared_ptr.hpp
as follows:
...
template<class Y>
explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter<Y>()) // Y
must be complete
{
p->constructor() ; // single patch for my purpose
detail::sp_enable_shared_from_this( pn, p, p );
}
...
But obviously, I'd rather not do that. So I came up with:
template <typename T>
struct Bridge : public boost::shared_ptr<T> {
template <typename Y>
explicit Bridge(Y * y) : boost::shared_ptr<Y>(y) {
if (y) {
y->constructor() ;
}
}
} ;
But then, the guarantee given in the boost shared_ptr documenation
was broken:
Quote: shared_ptr<T> can be implicitly converted to shared_ptr<U>
whenever T* can be implicitly converted to U*. In
particular,
shared_ptr<T> is implicitly convertible to shared_ptr<T
const>,
to shared_ptr<U> where U is an accessible base of T, and to
shared_ptr<void>.
So, I added a copy constructor:
template <typename T>
struct Bridge : public boost::shared_ptr<T> {
template <typename Y>
explicit Bridge(Y * y) : boost::shared_ptr<Y>(y) {
if (y) {
y->javaConstructor() ;
}
}
template<typename Y>
Bridge(Bridge<Y> const & r) : boost::shared_ptr<Y>(r) {
}
} ;
But then I get:
/Users/verec/Tools/boost_1_32_0/osx/main.cpp: In constructor
`Bridge<T>::Bridge(const Bridge<Y>&) [with Y = DisplayStruct, T =
DeviceStruct]':
/Users/verec/Tools/boost_1_32_0/osx/main.cpp:243: instantiated from
here
/Users/verec/Tools/boost_1_32_0/osx/main.cpp:21: error: type 'class
boost::shared_ptr<DisplayStruct>' is not a direct base of
'Bridge<DeviceStruct>'
Here's the relevant part of the code:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include
Jean-François Brouillet wrote:
So, I added a copy constructor:
template <typename T> struct Bridge : public boost::shared_ptr<T> {
template <typename Y> explicit Bridge(Y * y) : boost::shared_ptr<Y>(y) { if (y) { y->javaConstructor() ; } }
template<typename Y> Bridge(Bridge<Y> const & r) : boost::shared_ptr<Y>(r) { } } ;
But then I get:
/Users/verec/Tools/boost_1_32_0/osx/main.cpp:21: error: type 'class boost::shared_ptr<DisplayStruct>' is not a direct base of 'Bridge<DeviceStruct>'
That's because shared_ptr<Y> is not a base of Bridge<T>, shared_ptr<T> is. Change the templated copy constructor to: template<typename Y> Bridge(Bridge<Y> const & r) : boost::shared_ptr<T>(r) { } and it will compile. You can also use a static create function: class Display { public: typedef shared_ptr<Display> ref; static ref create() { ref r( new Display ); r->constructor(); return r; } private: Display() { ... } }; int main() { Display::ref d = Display::create(); }
On 2005-05-08 13:28:29 +0100, "Peter Dimov"
template<typename Y> Bridge(Bridge<Y> const & r) : boost::shared_ptr<Y>(r) { }
That's because shared_ptr<Y> is not a base of Bridge<T>, shared_ptr<T> is . Change the templated copy constructor to:
template<typename Y> Bridge(Bridge<Y> const & r) : boost::shared_ptr<T>(r) { }
<red faced> I had to read "spot the changes" your definition three times before I noticed that you had changed my Y with a T. And *that* was it. One thousand thanks, Peter!. -- Do your users a favor: give them Style: http://www.uiwithstyle.org
participants (2)
-
Jean-François Brouillet
-
Peter Dimov