I frequently use COM, and I've written an add_ref() and release() so that I can use my COM objects with boost::intrusive_ptr. However, one generally obtains these pointers through a library call that accepts a T** or a void**, and returns a pointer that's already been AddRef'd the first time. Normally it would go something like this:
template<typename T>
d3d_ptr<T> take_ptr(T* t) { return d3d_ptr<T>(t, false); }
ID3DXFont* pFont = NULL;
D3DXCreateFontIndirect(m_pDeviceObject, &fontDesc, &pFont);
m_spFont = take_ptr(pFont);
To remove these extra 2 lines I wrote the following class / function:
template<typename T>
class recv_by_addr_t
{
public:
recv_by_addr_t(d3d_ptr<T>& r) : m_auto(r), m_raw(NULL) {}
~recv_by_addr_t() {m_auto = take_ptr(m_raw);}
operator T**() { return &m_raw; }
private:
T* m_raw;
d3d_ptr<T>& m_auto;
};
template<typename T>
recv_by_addr_t<T> recv_by_addr(d3d_ptr<T>& rptr)
{
return recv_by_addr_t<T>(rptr);
}
And I can now call the function like this:
D3DXCreateFontIndirect(m_pDeviceObject, &fontDesc, recv_by_addr(m_spFont));
I feel like this is pretty solid, but figured I should ask the gurus :) Even in the case where the function errors out and sets the thing to NULL, the original pointer should still get correctly released. Anything wrong with this approach?