tags:

views:

139

answers:

4

Hi, i am using Xerces to do some xml writing.

here's a couple of lines extracted from my code:

DOMLSSerializer *serializer = ((DOMImplementationLS*)implementation)->createLSSerializer();
serializer->release();

Is there a boost smart pointer that i can use, so i can avoid calling serializer->release(); as it's not exception safe. The problem as i see it is that smart pointers can only call delete on your pointer object, could it be customised to call release?

thanks

+8  A: 

Yes, smart pointers can call a custom "deleter" function object.

#include <iostream>
#include <tr1/memory>
struct Example {
    void release() { std::cout << "Example::release() called\n"; }
};
struct ExampleDeleter {
        void operator()(Example* e) { e->release(); }
};
int main()
{
        {
        std::tr1::shared_ptr<Example> p ( new Example, ExampleDeleter() );
        }
        std::cout << " see?\n";
}

(same for boost: see the shared_ptr(Y * p, D d); constructor.)

Cubbi
@Greg Domjan's answer with `mem_fun` is actually better for simple cases such as this.
Cubbi
+3  A: 

Yes, boost::shared_ptr can be used with a custom deleter functor (as shown by Cubbi) or a deleter function:

void my_deleter(DOMLSSerializer* s) {
    s->release();
}

// ...
boost::shared_ptr<DOMLSSerializer> serializer(foo->createLSSerializer(), my_deleter);
Georg Fritzsche
A: 

If you just need a tiny RAII class then you could write the helper class yourself. It's so small that it barely pulls its own weight (let alone justifies pulling in a library):

class DOMLSSerializerOwner {
public:
  DOMLSSSerializerOwner( DOMLSSerializer *serializer ) : m_serializer( serializer ) { }
  ~DOMLSSerializerOwner() { m_serializer->release(); }

  operator DOMLSSerializer*() { return m_serializer; }

private:
  DOMLSSerializerOwner( const DOMLSSerializerOwner &other ); // disabled
  void operator=( const DOMLSSerializerOwner &rhs ); // disabled

  DOMLSSerializer *m_serializer;
};

Then you can make your code read:

void f()
{
  DOMLSSerializerOwner serializer = ((DOMImplementationLS*)implementation)->createLSSerializer();
  serializer->doThis();
  serializer->doThis();
  // Look Ma: no release() call; 'serializer' does it automatically when going out of scope
}
Frerich Raabe
`operator T*` isn't sufficient, you'd at least need `operator->`. Also implicit conversion is not always welcome, an explicit getter for the pointer value is better.
Georg Fritzsche
+2  A: 

Don't know why people write their own wrapper that way any more @Cubbi

As answered to make shared ptr not use delete

shared_ptr<DOMLSSerializer> serializer( 
  ((DOMImplementationLS*)implementation)->createLSSerializer(), 
  std::mem_fun(&DOMLSSerializer::release) );
Greg Domjan
You're right, but isn't it `std::mem_fun` since it's going to be called with a pointer? In my example, `shared_ptr<Example> p (new Example, std::mem_fun(` works and `...mem_fun_ref...` doesn't compile.
Cubbi
Quite right, thanks for the correction.
Greg Domjan