Overriding a [[noreturn]] virtual function

后端 未结 3 1864
小蘑菇
小蘑菇 2021-01-07 19:26

The [[noreturn]] attribute can be applied to functions that are not meant to return. For example:

[[noreturn]] void will_throw() { throw std::r         


        
相关标签:
3条回答
  • 2021-01-07 20:10

    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.

    0 讨论(0)
  • 2021-01-07 20:14

    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.

    0 讨论(0)
  • 2021-01-07 20:24

    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.

    0 讨论(0)
提交回复
热议问题