Overriding a [[noreturn]] virtual function

允我心安 提交于 2019-12-23 06:48:28

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!