inline
is redundant because: [dcl.constexpr]/1:
A function or static data member declared with the constexpr
or consteval
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.
consteval
functions. – Analisaanalise