ice
ice copied to clipboard
C++ exception "what" refactoring
std::exception::what is a virtual function that returns a const char*. A difficulty is where to store this message. We currently store it in IceUtil::Exception where it's computed lazily:
https://github.com/zeroc-ice/ice/blob/c962e53fd5613d4fe036f60bcaec3c75e00d7c78/cpp/src/IceUtil/UtilException.cpp#L523
This proposal gets rid of this lazy computation, by computing the what message in the constructor of the "derived" exception:
Step 1:
- change ice_staticId() and ice_id() to return a
const char*(not a string_view or string). - it's an easy change since all these ids are string literals
Step 2:
- change Ice::Exception::what() to return ice_id()
Step 3:
- if an exception wants a custom message, it creates its own private
string _what;
field and fills in its constructor using its own private non-virtual ice_print helper function. For example:
class BadMagicException : public ProtocolException
{
public:
// don't inherit base constructor(s)
BadMagicException(const char* file, int line, std::string reason, ByteSeq badMagic) // no longer noexcept?
: ProtocolException(file, line, std::move(reason)),
badMagic(std::move(badMagic)) // should be out of line
{
ostringstream os;
ice_print(os);
_what = os.str();
}
static const char* ice_staticId() { return "::Ice::BadMagicException"; } // should be out of line
const char* ice_id() const noexcept override { return ice_staticId(); } // should be out of line
const char* what() const noexcept override { return _what; } // should be out of line
const string reason; // now const
const ByteSeq badMagic;
private:
void ice_print(std::ostream&) { ... "prints" custom message } // should be out of line
std::string _what; // stores the custom message for this class
};
For user exceptions, this proposal maintains compatibility with the existing cpp:ice_print metadata.