There is nothing preventing you from returning an error code from a constructor by throwing an exception.
You just need to derive your own exception class from std::runtime_error
:
#include <stdexcept> // for std::runtime_error
#include <windows.h> // for HRESULT
class com_error : public std::runtime_error
{
HRESULT hr;
public:
com_error(const char *_Message, const HRESULT _hr)
: std::runtime_error(_Message)
, hr(_hr)
{
}
HRESULT error_code() const noexcept
{
return hr;
}
};
Now you can throw an exception which contains error code:
class A
{
public:
A()
{
HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (SUCCEEDED(hr)) {
// TODO: continue initialization
} else {
throw com_error("COM initialization failed", hr);
}
}
};
And you can catch it and examine the error code:
try {
A *a = new A();
// ...
} catch (com_error& e) {
HRESULT hr = e.error_code();
// TODO: Do what you want with error code here
}
That doesn't mean it is a good idea. It is better to use Initialize / Shutdown pattern when the object construction is complex and might require cleanup / rollback.