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 classesinline
- compiler should attempt to generate code for a call to f
rather than calling it normallyconst
- the function is not able to change any of S
's membersnoexcept
- the function will never throw (cannot throw or not allowed to throw)const
pointer to a const unsigned long int
auto .... -> void
- suffix return type void
[[noreturn]]
- it never return
sHere are my main concerns:
[[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?int
instead of void
for example? }
)?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
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?
From this Q&A you can see that noreturn is a way to tell the compiler that a function does not return. Normally this means it either has an infinite loop (often seen in servers that are supposed to run indefinitely) or it calls exit()
, terminate()
and the like, exiting the application without returning to main.[[noreturn]]
is optional, i.e. you don't have to specify it. It's an attribute, i.e. the basic syntax of defining/declaring the function remains untouched, so the function has to have a return type as any other function has.
Would this code compile with int instead of void for example?
Yes, it would, although the compiler might warn you that it does not make sense having something returned from a function that never returns.
What would be a practical use for a function like that? To throw an exception?
The first thing that comes to mind is some endless loop, e.g. handling incoming requests at a server. Throwing an exception is ok for [[noreturn]]
functions as well, but its not really an option here, because it explicitly says noexcept
. Throwing would trigger a call to std::terminate()
, leading to program termination itself but previosuly to an implementation defined amount of stack unwinding, wich in fact means [[noreturn]]
would still be applicable.
Where does the flow of the code go after this function finishes executing (after } )?
The function never reaches its closing }
. It either runs endlessly (until someone pulls the plug), or it exits abnormally, i.e. by program termination. In other words, if the function does not execute any more, it has not really finished but aborted execution, and there is no program and no control flow to go to.
The other answers are great, but I'm going to present an alternative answer for
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?
One reason why you might need a return type (and a non-void return type at that) is if the function is overriding a super classes method.
struct Parent {
virtual int f()=0;
}
struct Child {
[[noreturn]] override int f() noexcept { ... }
};
In some contexts the compiler will be able to use the [[noreturn]]
to produce better code. But in other situations f
might be called polymorhically, and thus needs to conform to its parents signature.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With