Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should `constexpr` functions also be `noexcept`?

Tags:

c++

c++11

When I define a constexpr function, should I also declare it as noexcept? I imagine in the case where the arguments and usage satisfy the requirements for compile-time evaluation, the meaning of potential exceptions is moot. But it would apply as normal for cases when the function is evaluated at run time.

As a matter of practical concern, if the function is indeed simple, perhaps using built-in arithmetic or a cast, such that I expect the compiler can always inline the function and optimize across it, does it matter to the efficiency of the generated code if I leave off noexcept?

like image 712
JDługosz Avatar asked Feb 29 '16 09:02

JDługosz


People also ask

Is constexpr a Noexcept?

No, in general it doesn't. A constexpr function can be invoked in a non-constepr context in which it is allowed to throw an exception (except of course if you manually specify it to be noexcept(true) ).

Are constexpr functions evaluated at compile time?

A constexpr function is one whose return value is computable at compile time when consuming code requires it. Consuming code requires the return value at compile time to initialize a constexpr variable, or to provide a non-type template argument.

Can a constexpr function throw an exception?

Even though try blocks and inline assembly are allowed in constexpr functions, throwing exceptions or executing the assembly is still disallowed in a constant expression.

Are constexpr functions inline?

A constexpr constructor is implicitly inline.


1 Answers

No, you should not.

"Cannot fail" and "can be evaluated at compile time" are orthogonal issues. For example, you want to write an integer power function, but you want to take the power as signed (because you believe that unsigned numbers should only be used for very special cases). Now you say you want to throw an exception if the power is negative. In C++14 you can write it like this:

constexpr int ipow(int base, int power) {
  if (power < 0) throw std::domain_error("negative power");
  int result = 1;
  for (int i = 0; i < power; ++i) result *= base;
  return result;
}

This function clearly isn't noexcept, but for non-negative arguments, you obviously can evaluate it at compile time. If you try it for negative arguments in a context where you need the result at compile time, you get a compile error, which should be fine.

like image 103
Sebastian Redl Avatar answered Sep 27 '22 19:09

Sebastian Redl