[C++-sig] Problems with custom smart pointers and multiple inheritance

Chris Christophe.Gratin at adcis.net
Wed Mar 22 13:59:42 CET 2006


Thanks for your answer

 > If you use boost::shared_ptr, it sort of works.  With any other smart
 > pointer you can't really do it as far as I know.  There's some ongoing
 > discussion about this.  I would like to fix it.

This could be a solution, but will it still work if I define MyPointer<T> as a class derived from 
shared_ptr<T>. That's what I am eventually trying to do, but I still can't call my PassAPointer() 
function. I get the following runtime error (my source code is pasted below):

     print c1.PassAPointer(c1)   # fails
Boost.Python.ArgumentError: Python argument types in MyBaseA.PassAPointer(MyClass, MyClass) did not 
match C++ signature:
     PassAPointer(class MyNamespace::MyBaseA {lvalue}, class MyNamespace::MyPointer<class 
MyNamespace::MyBaseA>)


Note that it works perfectly if I simply "#define MyPointer shared_ptr" instead of using my derived 
template class.

I guess there is surely something simple to add to make it work. At least I hope so.

Chris.

-----------
namespace MyNamespace
{
#ifdef USE_DERIVED
   template <class T> class MyPointer: public shared_ptr<T>
   {
   public:
     template<class Y> explicit MyPointer(Y* p): shared_ptr<T>(p) {}

     template <class Y> MyPointer(const shared_ptr<Y>& p): shared_ptr<T>(p) {}

     MyPointer() {}
   };
#else
   #define MyPointer shared_ptr
#endif

   class MyBaseA
   {
   public:
     typedef MyPointer<MyBaseA> Ptr;

     virtual std::string PassAPointer(MyBaseA::Ptr value) = 0;
   };

   class MyBaseB
   {
   public:
     typedef MyPointer<MyBaseB> Ptr;

     virtual std::string PassBPointer(MyBaseB::Ptr value) = 0;
   };

   class MyClass:
     public MyBaseA,
     public MyBaseB
   {
   public:
     typedef MyPointer<MyClass> Ptr;

     std::string PassAPointer(MyBaseA::Ptr value)
     {
       return (boost::format("PassAPointer - %1%") % int(this)).str();
     }

     std::string PassBPointer(MyBaseB::Ptr value)
     {
       return (boost::format("PassBPointer - %1%") % int(this)).str();
     }
   };
}

using namespace MyNamespace;

BOOST_PYTHON_MODULE(MyModule)
{
   class_<MyBaseA, MyBaseA::Ptr, boost::noncopyable>("MyBaseA", no_init)
     .def("PassAPointer", &MyBaseA::PassAPointer)
   ;

   class_<MyBaseB, MyBaseB::Ptr, boost::noncopyable>("MyBaseB", no_init)
     .def("PassBPointer", &MyBaseB::PassBPointer)
   ;

   class_<MyClass, MyClass::Ptr, boost::noncopyable, bases<MyBaseA, MyBaseB> >("MyClass", init<>())
   ;
}


Python test code

   c1 = MyModule.MyClass()
   print c1.PassAPointer(c1)  # fails




More information about the Cplusplus-sig mailing list