Boost logo

Boost Users :

From: Bruno Martínez (br1_at_[hidden])
Date: 2005-11-29 08:00:01


On Tue, 29 Nov 2005 06:53:07 -0200, eric <spamsink42_at_[hidden]> wrote:

> Can I declare a pure virtual member function which accepts as input a
> boost shared pointer to an object of a base class, such that
>
> - clients of the function can pass in as input a boost shared pointer
> to an object of a derived class
>
> - concrete implementations of the function can redirect the pointer to
> a new object of an (even more) derived class
>
> ?
>
>
>
> Consider the following class hierarchy in the problem domain:
>
>
>
> class Serializable {};
>
> class Foo : public Serializable {};
>
> class Bar : public Foo {};
>
>
>
> Here is the pure virtual member function I would like to declare:
>
>
>
> class Serializer {
>
> public:
>
> virtual void serializeObject(boost::shared_ptr < Serializable >
> &) = 0;
>
> }
>
>
>
> And the relevant subset of one of its concrete implementations:
>
>
>
> class XmlReader : public Serializer {
>
> virtual void serializeObject(boost::shared_ptr < Serializable >
> &p) {
>
> p = boost::shared_ptr < Serializable > (new Bar());
>
> }
>
> }
>
>
>
> The client would call the function like this:
>
>
>
> boost::shared_ptr < Foo > foo;
>
> Serializer *s = new XmlReader();
>
> s->serializeObject(foo);
>
>
>
> The above code doesn't compile, the error message from VC6 is
>
>
>
> main.cpp(72) : error C2664: 'serializeObject' : cannot convert
> parameter 1
> from 'class boost::shared_ptr<class Foo>'
> to 'class boost::shared_ptr<class Serializable> &'

I think that what you're trying to do isn't sound. IIUC, it's the same as

     Foo* fp = 0;
     Serializable*& spr = fp;

this breaks typing rules because then fp would be able to hold objects not
derived from Foo.

> The best solution I have found so far is to declare the function like
> this:
>
>
>
> class XmlReader : public Serializer {
>
> virtual boost::shared_ptr < Serializable > serializeObject() {
>
> boost::shared_ptr < Serializable > ret =
>
> boost::shared_ptr < Serializable > (new Bar());
>
> return ret;
>
> }
>
> }
>
>
>
> And call it like this:
>
>
>
> foo = boost::dynamic_pointer_cast< Foo >(s->serializeObject());
>
>
>
> But that's not ideal for my purposes, I would prefer to have a
> function which modifies its inputs and returns void.
>
>
>
> I can't implement the function as a template because I need it to be
> virtual.

I don't see how to implement this without some extra work. One way would
be:

#include <boost/shared_ptr.hpp>

class Serializable {
public:
     virtual ~Serializable() {}
};
class Foo : public Serializable {};
class Bar : public Foo {};

class Serializer {
public:
     template<class T>
     void serializeObject(boost::shared_ptr<T>& p) {
         boost::shared_ptr<Serializable> aux(p);
         serializeObjectImpl(aux);
         p = boost::dynamic_pointer_cast<T> (aux);
     }
private:
     virtual void serializeObjectImpl(boost::shared_ptr<Serializable>&) = 0;
};

class XmlReader : public Serializer {
     virtual void serializeObjectImpl(boost::shared_ptr<Serializable>& p) {
         p.reset(new Bar);
     }
};

int main()
{
     boost::shared_ptr < Foo > foo;
     Serializer *s = new XmlReader();
     s->serializeObject(foo);
}

Bruno


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