I am working with some code in which constexpr
functions are used which I currently refactor to be consteval
whenever possible.
inline constexpr auto example() noexcept { /*...*/ }
As I understand it, the inline
keyword above is already redundant in the constexpr
function.
As far as I understand it, the noexcept
keywords are redundant for consteval
functions, because as I understand it consteval
has to be evaluated at compile time, and hence implies noexcept. Is this true or might there be something I currently do not consider (like constexpr exceptions
)?
consteval auto example() { /*...*/ }
Also, note that constexpr variables are inline implicitly, so there's no need to use constexpr inline myVar = 10; . Why can it simplify the code? For example, a lot of header only libraries can limit the number of hacks (like using inline functions or templates) and just use inline variables.
A constexpr specifier used in a function or static data member (since C++17) declaration implies inline .
inline
is redundant because: [dcl.constexpr]/1:
A function or static data member declared with the
constexpr
orconsteval
specifier is implicitly an inline function or variable ([dcl.inline]).
noexcept
is somewhat more interesting. It is true that an attempt to throw an exception (whether via throw
, dynamic_cast
, or typeid
) is not allowed during constant evaluation time ([expr.const]/5.24). And since a consteval
function is only evaluated during constant evaluation time, the noexcept
has minimal benefit - an exception will certainly never escape this scope. And, moreover, you can't even have a function pointer to these functions leak to runtime either. There really is no mechanism I can think of for which this would be relevant.
However, perhaps at some point in the future, might we be allowed to have exceptions during constant evaluation? And if we go there, would it become important to know about noexcept
-ness in that world? An exception that leaks out of a constant evaluation context would likely have to mean a compile error, so might you have algorithms that make different choices based on the noexcept
-ness of a consteval function?
That said, I'd skip the noexcept
. It certainly has no benefit now, and it may not even have benefit in the future. And if I end up being wrong then... I'm sorry.
Although really, as T.C. points out, it's not that simple:
consteval int current() { return 1; }
void f(int, int = current()) noexcept;
What's noexcept(f(1))
? As written, it's false
. And that's pretty weird right, since this the expression f(1)
definitely isn't going to throw. So maybe you should write noexcept
. Although since again it definitely can't throw, maybe the language should make consteval
functions noexcept
by default. Although if we do that, and do eventually add exceptions during constant evaluation time... now we're back to lying again since that's something we won't be able to claw back.
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