Search code examples
c++functionreturnnoreturn

How can a [[noreturn]] function have a return type?


I encountered this "beautiful" example of "highly readable" and "elegant" code, but I'm having troubles understanding it:

struct S {

    [[noreturn]] virtual inline auto f(const unsigned long int *const)
                         –> void const noexcept;
};

Here's what I understand (please correct me if I'm wrong):

  • f() is a member function of S
  • virtual - can be overridden by derived classes
  • inline - compiler should attempt to generate code for a call to f rather than calling it normally
  • const - the function is not able to change any of S's members
  • noexcept - the function will never throw (cannot throw or not allowed to throw)
  • parameter: a const pointer to a const unsigned long int
  • auto .... -> void - suffix return type void
  • [[noreturn]] - it never returns

Here are my main concerns:

  • If a function is declared as [[noreturn]], it never returns to its caller; so how can it have a return type void? What is the point of a return type in this function anyway?
  • Would this code compile with int instead of void for example?
  • What would be a practical use for a function like that? To throw an exception?
  • Where does the flow of the code go after this function finishes executing (after } )?

I couldn't get this code to run on VS2013 Preview, so I guess these features weren't implemented yet.

I'm very curious about this, so I'll appreciate it if someone can explain! Cheers


Solution

  • The [[noreturn]] is an attribute which has whatever semantics it has. It doesn't change, however, how the function is declared: all normal functions in C++ (i.e., all functions except the constructors, destructors, and conversion operators) have a declared return type. Adding any attribute doesn't change this rule.

    The purpose of the [[noreturn]] attribute is probably to indicate that the function never returns in a normal way. Given that the function is also declared to be noexcept it basically means that the corresponding function also can't thrown an exception. One example of a function with similar behavior is exit() which terminates the program. I could imagine that functions implementing some sort of application-loop could also qualify. In any case, the [[noreturn]] tells the system that the corresponding function will never normally return, i.e., falling off the function ("after }") will probably result in undefined behavior.