Working with the D3D API involves handling API resources via pointers. The API user is responsible for disposing of those resources.
In the spirit of modern C++ style, this is a job for some sort of smart pointer. But unique_ptr isn't a great fit, for a couple of reasons.
The way resources are acquired
The D3D API produces resources via "out parameters", which would require explict temporary pointers to transport resource addresses to owning unique_ptrs:
resource_type * pResource; // Temporary pointer.
D3D_Make_Resource(&pResource); // D3D style of producing resources.
upResource.reset(pResource); // unique_ptr's style of assigning.
The way resources are freed
D3D resources are released, not deleted. Not only would unique_ptr require a custom deleter type to free the resources, it would require a unique deleter type per resource type, because each resource class has its own member Release() method, rather than sharing a common non-member function, like delete():
unique_ptr<resource_type, resource_releaser<resource_type>> upResource;
These aren't exactly show stoppers, but they're enough to take a couple of minutes to see if I can't do a little better. So I threw together a resource pointer class along the lines of this:
template<typename T> class d3d_resource_ptr
{
public:
d3d_resource_ptr() : pResource(nullptr) {}
~d3d_resource_ptr() {Release();}
T & operator * () const {return *pResource;} // Dereferencing works
T * operator -> () const {return pResource;} // like a normal pointer.
private:
d3d_resource_ptr (d3d_resource_ptr const &); // Unique ownership. No need
d3d_resource_ptr & operator = (d3d_resource_ptr const &); // for copying (or moving).
void Release() {if(pResource != nullptr){pResource->Release();} pResource = nullptr;}
T * pResource;
};
The question is how best to get and set the raw pointer. Which is the lesser evil?
We could use a reference operator and implicit pointer conversion:
public:
T * * operator & () {Release(); return &pResource;} // Pointer to pointer, for reassignment.
operator T * () const {return pResource;} // Conversion to T pointer, for storage or passing.
Which provides about as much convenience as possible:
D3D_Make_Resource(&rpResource); // operator & passes a T * * so the API can assign through it.
D3D_Use_Resource(rpPesource); // operator T * generates a T * so the API can use it.
The evil here is that the resource pointer interface is a little too clever. It's hiding the fact that taking a reference automatically releases any resource (in anticipation of assigning a new one). That's an accident waiting to happen. And I suspect that implicit pointer conversions are trouble makers as well.
Alternatively, we could use explicit functions:
public:
T * Get() const {return pResource;}
T * * Assign() {Release(); return &pResource;}
private:
d3d_resource_ptr * operator & (); // Protect against errant references.
Which produces code like this:
D3D_Make_Resource(rpResource.Assign());
D3D_Use_Resource(rpResource.Get());
I guess the thing that bugs me the most about this is that I can't think of a better name for Assign(). I don't think its intention is entirely clear. What is clear is that this approach is not as clean as the previous option, and adds noise to already noisy function calls which handle several resources at a time.
So which is the lesser of the two evils? Or is there another way which is even less evil?
Would this be better or worse? :
public:
void Release() {if(pResource != nullptr){pResource->Release();} pResource = nullptr;} // Now public.
T * * operator & () {assert(pResource == nullptr); return &pResource;} // Require Release() rather than calling it.