std::exception requires that its constructor be throw(). Yet std::runtime_error accepts a std::string as its argument, which indicates that it’s storing a std::string somewhere. Therefore, an assignment or copy construction has to be going on somewhere. And for std::string, that’s not a nothrow operation.
How then does runtime_error::runtime_error meet throw()?
(For context, I’m implementing an exception type, and want to store a few std::strings from the call site, and I want to do it correctly…)
(Here’s the same thing in a minimal-ish testcase.)
runtime_error::runtime_error(string const&)doesn’t need to meetthrow().It doesn’t inherit from or override
exception::exception(), and by the timestring‘s copy constructor is invoked,exception::exception()has completed.If copying the
stringwere to throw an exception, this would unwindruntime_error::runtime_error(string const&)and then, I suppose, invokeexception::~exception().It’s hard to directly show that there is no requirement of a derived ctor to meet a base ctor’s exception specifier, but it is strongly implied by the following passage (which describes how the base’s destructor is invoked, rather than passing the exception into the base constructor):
The only passage which comes even close to the scenario you presumed (and which I initially presumed) is the following.
But clearly
exception::exception()is not a virtual function, and clearlyruntime_error::runtime_error(string const&)does not override it.(Note that this scenario would apply for a virtual destructor; accordingly, you can see that, in libstdc++,
runtime_error::~runtime_error()isthrow()).