views:

75

answers:

2

I do receive a shared_ptr from a library call, and pass it and some resource back into the library. The resource can only be deleted when the shared_ptr deletes its pointer:

std::ofstream* out = new std::ofstream(); 
...
shared_ptr<Lib::SomeClass> writer = Library.createWriter(out);

Library.appendWriter(writer);

The library expects me to manage out* but does not tell when it is safe to do so. Essentially, I want out to be deleted if writer is released.

Can this be achieved using the deleter facility of boost? Ideas?

+1  A: 

I don't believe you can do this directly with the shared_ptr API.

If Lib::SomeClass is an interface/abstract base class, you might be able to use a Decorator. The idea would be to define a class which subclasses Lib::SomeClass, contains a shared_ptr<Lib::SomeClass> and a std::ofstream*, and whose methods all forward to the corresponding method of the contained shared_ptr. The decorator's destructor, however, would delete the contained ofstream (or you could store it in some sort of RAII container like a scoped_ptr). So it would be an instance of the Decorator that you passed to appendWriter. Here's a sketch:

class SomeClassDecorator : public Lib::SomeClass
{
  public:
    SomeClassDecorator(shared_ptr<Lib::SomeClass> p, std::ofstream* stream)
      : p_(p), stream_(stream)
    {}

    virtual int MethodOfSomeClass(int x) {
        return p_->MethodOfSomeClass(x);
    }

  private:
    shared_ptr<Lib::SomeClass> p_;
    scoped_ptr<std::ofstream> stream_;
};

std::ofstream* out = new std::ofstream(); 
...
shared_ptr<Lib::SomeClass> writer = Library.createWriter(out);
shared_ptr<Lib::SomeClass> wrapper(new SomeClassDecorator(writer, out));

Library.appendWriter(wrapper);
SCFrench
Thanks! `writer` is indeed an interface, so this approach works nicely!
Christopher Oezbek
+1  A: 

You could try to create the output stream on the stack in a scope that is guaranteed to live longer than any reference to writer. It depends on your architecture, whether this is possible (although I would argue that in a good architecture it should be).

If you have the chance to negotiate with the library designer (as you mentioned in your comment), tell him/her to take the argument as a reference if that is sufficient. A shared_ptr should only be used if the ownership of the object is really shared.

Space_C0wb0y
Unfortunately, the API design is crooked here. The stack does not live long enough to see the end of writer being used.
Christopher Oezbek
@Christopher Oezbek: Well, some stack-frame has got to live at least as long as the last pointer. But I admit that it may even worse design to put the output stream somewhere where is doesn't belong just for that.
Space_C0wb0y