2

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

dangerousdave
  • 6,331
  • 8
  • 45
  • 62
  • If you don't want to call release because it's now exception safe, how would a smart pointer help if you expect it to call release itself? – Patrick Jul 09 '10 at 12:55
  • Sorry, i meant its not save to call release() as i have illustrated above, as it may not get called when an exception is thrown. – dangerousdave Jul 09 '10 at 13:03

4 Answers4

8

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
  • 46,567
  • 13
  • 103
  • 169
3

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
  • 97,545
  • 26
  • 194
  • 236
2

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) );
Community
  • 1
  • 1
Greg Domjan
  • 13,943
  • 6
  • 43
  • 59
  • 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 p (new Example, std::mem_fun(&Example::release));` works and `...mem_fun_ref...` doesn't compile. – Cubbi Jul 09 '10 at 17:48
0

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
  • 90,689
  • 19
  • 115
  • 207
  • 1
    `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 Jul 09 '10 at 13:15