izazu
izazu

Reputation: 87

Making a template function work with both lvalue and rvalues pointer arguments

I currently have a memory leak in my project. To resolve the memory leak, I am trying to replace the pointers into std:: unique_ptr. The pointer to the heap is not from my project, but rather from a library called Xerces(an XML parsing library). In this library, it can transcodes char * to XMLCh * in both ways. So in real code, it comes like ..

XMLCh * xmlstr = XMLString::transcode("abc",...);
char * charstr = XMLString::transcode(xmlstr,...);

since both methods allocates heap area and returns the pointer for it, I should explicitly call

XMLString::release(xmlstr);
XMLString::release(charstr);

after using it to clean up. I want to write a custom deleter for two types (char * and XMLCh *) using std::unique_ptr.

The release method has a type of

XMLString::release(char **str);
XMLString::release(XMLCh **str);

It is using double pointer because it sets the pointer to null after release. I thought to make the template accept reference pointers like this,

template<typename T>
void release(T *& ptr){
    XMLString::release(ptr);
}

but just realized that it will be possible to

XMLCh * xmlstr = XMLString::transcode("abc",...);
auto uptr = unique_ptr<XMLCH, decltype(&release<T>)>(xmlstr)

do this, but not possible to

auto  xmluptr = unique_ptr<XMLCH, decltype(&release<T>)>(XMLString::transcode("abc",...));

do something like this, because it is accepting a rvalue in the parameter but the argument is a reference pointer. Is it possible to instantiate both cases writing only one template function? By the way, I am using c++11.

Upvotes: 0

Views: 92

Answers (1)

Jan Hudec
Jan Hudec

Reputation: 76256

So if I understand correctly, your problem is that XMLString::release takes a pointer-to-point and it does not fit into the unique_ptr release function. Well, the correct solution is to wrap it like

template<typename T>
void release(T *ptr){
    XMLString::release(&ptr);
}

The XMLString::release will only null-out the copy of the pointer inside the wrapper, but since the unique_ptr takes care of rendering itself unusable itself, you don't need that functionality of XMLString::release.

In either case, the type of the release wrapper does not affect how the unique_ptr is constructed, because the release wrapper will be called with the internal member of the unique_ptr as argument. So either unique_ptr accepts that argument, and both assignments will work, or unique_ptr won't accept it and neither will.

That said, the point of unique_ptr is that you wrap the pointer in it immediately when you get it. So don't store it in variable before.

Upvotes: 2

Related Questions