I have a function like this:
bool op1();
bool op2();
bool foo() {
CoInitialize(nullptr);
if (!op1()) {
CoUninitialize();
return false;
}
// do more stuff, then call op2...
if (!op2()) {
CoUninitialize();
return false;
}
// happy path
CoUninitialize();
return true;
}
I want to refactor foo()
to throw exceptions:
void foo() {
CoInitialize(nullptr);
if (!op1()) {
CoUninitialize(); // I'm lazy, can't I automate this call?
throw std::exception("Failed");
}
// ...
But I have to call CoUninitialize()
each time I have an error.
I thought about wrapping the COM init calls inside a class, so the destructor will do the cleanup, but having an unused object feels strange to my eyes:
class comlib {
public:
comlib() { CoInitialize(nullptr); }
~comlib() { CoUninitialize(); } // automated!
};
void foo() {
comlib nobodyEverCallsMe;
if (!op1()) {
throw std::exception("Failed");
}
// ...
Is there a better approach to this?
Raymond Chen has been using this method for a while so I'm sure it's OK, just remember to only call CoUninitialize
if CoInitialize
SUCCEEDED
!
class CCoInitialize {
HRESULT m_hr;
public:
CCoInitialize() : m_hr(CoInitialize(NULL)) { }
~CCoInitialize() { if (SUCCEEDED(m_hr)) CoUninitialize(); }
operator HRESULT() const { return m_hr; }
};
void Something()
{
CCoInitialize init;
...
}
Some people might want to throw in the constructor if CoInitialize fails but I feel that's unnecessary because other COM calls down the line will fail. Only do it if you need to capture the exact HRESULT failure code from CoInitialize.