The WIL RETURN_
macro evaluates its argument, and if it is a COM failure HRESULT
, then it returns immediately from the function with that HRESULT
. There is also a RETURN_
macro that behaves the same, except that any failures are not recorded in the error log. The EXPECTED
version is for the case where a function fails, but you don’t want it cluttering your error log.
But one case that’s not covered is “Call this function, and return immediately if the call fails, except that certain errors should be ignored and allow execution to continue.” How do you do that?
You can build a filter function that you send the result through, and the filter function can convert all the harmless errors into S_OK
.
HRESULT AllowPending(HRESULT hr) { if (hr == E_PENDING) return S_OK; return hr; }
You can then combine this with RETURN_
:
RETURN_IF_FAILED(AllowPending(GetItem()));
You can even generalize this to allow the list of allowed errors to be passed as a parameter:
HRESULT IgnoreSpecificErrors( HRESULT hr, std::initializer_list<HRESULT> ignored) { for (auto candidate : ignored) { if (hr == candidate) return S_OK; } return hr; } RETURN_IF_FAILED(IgnoreSpecificErrors(GetItem(), { E_PENDING }));
You can also create sets of ignorable errors:
constexpr HRESULT rpc_errors[] { RPC_E_DISCONNECTED, RPC_E_SERVER_DIED, RPC_E_SERVER_DIED_DNE, }; RETURN_IF_FAILED(IgnoreSpecificErrors(GetItem(), rpc_errors));
The nice thing about using a filter function is that you can add whatever other features you like.
HRESULT IgnoreSpecificErrors( HRESULT hr, std::initializer_list<HRESULT> ignored) { for (auto candidate : ignored) { if (hr == candidate) { LOG_HR(hr); // log the failure before transforming it return S_OK; } } return hr; }
This seems to be a way to react to GetItem's semantics being "sometimes you don't get an item and that's okay"
A better approach is to rename the function to make this clear - call it TryGetItem()
If TryGetItem succeeds, great
If TryGetItem hits a real failure, have it return that failure, and let RETURN_IF_FAILED bubble that real error up the stack
If TryGetItem hits an ignorable error, have it return S_OK, but have some other indication that the...