Boost logo

Boost Users :

From: Jean-François Brouillet (verec_at_[hidden])
Date: 2005-05-07 21:12:23


- 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 <boost/shared_ptr.hpp>

struct ObjectStruct {
     ObjectStruct() { } ;
     virtual void constructor() { }
     virtual ~ObjectStruct() { }
} ;

typedef Bridge<ObjectStruct> Object ;

struct DeviceStruct : public ObjectStruct {
     typedef Bridge<DeviceStruct> Device ;

     DeviceStruct() { std::cout << "Device
standard c++ constructor." << std::endl ; }
     virtual void deviceMethod() { std::cout <<
"DeviceStruct::deviceMethod." << std::endl ; }
     virtual void constructor() { std::cout << "java's
Device::constructor." << std::endl ; }
     static Device current ;
     static Device getCurrent() { return current ; }
} ;

typedef Bridge<DeviceStruct> Device ;

struct DisplayStruct : public DeviceStruct {
     typedef Bridge<DisplayStruct> Display ;

     DisplayStruct() {
         std::cout << "Display standard c++ constructor." << std::endl ;
     }

     DisplayStruct() { std::cout << "Display
standard c++ constructor." << std::endl ; }
     virtual void constructor() { DeviceStruct::constructor
() ; std::cout << "java's Display::constructor." << std::endl ; }
     virtual void deviceMethod() { DeviceStruct::deviceMethod
() ; std::cout << "DisplayStruct::deviceMethod." << std::endl ; }
     virtual void displayMethod() { std::cout <<
"displayMethod." << std::endl ; }
} ;

typedef Bridge<DisplayStruct> Display ;

void
callDevice(Device d) {
     d->deviceMethod() ;
}

int main (int argc, char * const argv[]) {
     Display display(new Display) ;
     Device device(new DeviceStruct) ;

     callDevice(device) ;
     callDevice(display) ;

     return 0 ;
}

What am I missing ?

Many Thanks.

--
Jean-François Brouillet
verec_at_[hidden]

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net