Is it acceptable C++ style to let classes that wrap shared handles be copyable?
Very frequently I find myself writing classes that hide the details of some gnarly C library or OS resource by holding a shared_ptr to it behind the class interface. E.g.
class window
{
public:
window() : m_handle(OsCreateWindow(), OsDestroyWindow) {}
void make_it_dance();
void paint_it_red();
private:
shared_ptr<OS_WINDOW_HANDLE> m_handle;
}
Because the classes are copyable and shared_ptr
does the hard work, the instances can be passed around willy-nilly and nothing leaks or is destroyed twice. So, technically, all is good. I've been doing this for years.
But recently I've started to wonder whether this is really good style. After all, the object at the end of the handle isn't being duplicated when the class instance is. Would it be better to make all these classes non-copyable, making very clear to users that they're dealing with a reference to the same object? Modern C++ makes a big deal of being "value-based", and sharing the backend resource between instances seems to go against that principle.
However, the consequence would be that a large proportion of my code would deal in pointers, even if they are smart pointers. That seems a step backwards.