Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding a [[noreturn]] virtual function

Tags:

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.

like image 431
KyleKnoepfel Avatar asked Sep 18 '15 15:09

KyleKnoepfel


People also ask

What does [[ Noreturn ]] mean?

C++ attribute: noreturn (since C++11)Indicates that the function does not return.

Can you override a virtual function?

Because virtual functions are called only for objects of class types, you cannot declare global or static functions as virtual . The virtual keyword can be used when declaring overriding functions in a derived class, but it is unnecessary; overrides of virtual functions are always virtual.

Can we override virtual method in C++?

Use of C++ override Using the override identifier prompts the compiler to display error messages when these mistakes are made. Otherwise, the program will simply compile but the virtual function will not be overridden.

Do I need to override virtual functions?

It is not mandatory for the derived class to override (or re-define the virtual function), in that case, the base class version of the function is used. A class may have virtual destructor but it cannot have a virtual constructor.


2 Answers

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.

like image 185
Lightness Races in Orbit Avatar answered Sep 29 '22 06:09

Lightness Races in Orbit


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.

like image 32
TemplateRex Avatar answered Sep 29 '22 05:09

TemplateRex