The [[noreturn]]
attribute can be applied to functions that are not meant to return. For example:
[[noreturn]] void will_throw() { throw std::r
In practice, neither g++, clang nor MSVC consider the [[noreturn]]
attribute as inherited
#include <iostream>
struct B {
public:
[[noreturn]] virtual void f() { std::cout << "B\n"; throw 0; }
};
struct D : public B {
void f() override { std::cout << "D\n"; }
};
int main()
{
try { B{}.f(); } catch(...) {}
D{}.f();
B* d = new D{};
d->f();
}
which prints out "B", "D" and "D" for all three compilers.
Consider what you are actually saying:
class B
{
public:
[[noreturn]] virtual void f() { throw std::runtime_error(""); }
};
Certainly the human reader, and possibly the compiler, would interpret
this as a 'contract', i.e.
"f()
wont return, I promise"
That should then apply to overrides of f()
too, or else you are breaking the contract.
The standard might be underspecified on this, but even if it works, I would recommend against it based on readability.
I have grepped through the standard, and there's no indication that either [[noreturn]]
specifically, or attributes more generally, are "inherited" by overriding functions.
It's hard to prove a negative, and the standard actually doesn't declare this either way but, since A::f()
and B::f()
are still distinct functions and the only behaviour described is defined in terms of functions, I think you're safe to mark A::f()
as [[noreturn]]
.
That being said, I can't imagine what useful optimisation the compiler could subsequently perform, given the dynamic dispatch.