问题
The [[noreturn]]
attribute can be applied to functions that are not meant to return. For example:
[[noreturn]] void will_throw() { throw std::runtime_error("bad, bad, bad ...."); }
But I've encountered the following situation (no, I didn't design this):
class B {
public:
virtual void f() { throw std::runtime_error(""); }
};
class D : public B {
void f() override { std::cout << "Hi" << std::endl; }
};
I would really like to place the attribute [[noreturn]]
on the B::f()
declaration. But I'm unclear as to what happens to the override in the derived class. Successfully returning from a [[noreturn]]
function results in undefined behavior, and I certainly don't want that if an override also inherits the attribute.
The question: By overriding [[noreturn] virtual void B::f()
, do I inherit the [[noreturn]]
attribute?
I've looked through the C++14 standard, and I'm having trouble determining if attributes are inherited.
回答1:
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.
回答2:
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.
回答3:
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.
来源:https://stackoverflow.com/questions/32655526/overriding-a-noreturn-virtual-function