I'm working through 'Programming: Principles and Practice Using C' and need some help understanding this bit on constexpr
functions on page 291:
A constexpr function behaves just like an ordinary function until you use it where a constant is needed. Then, it is calculated at compile time provided its arguments are constant expressions (e.g., p2) and gives an error if they are not (e.g., p1). To enable that, a constexpr function must be so simple that the compiler (every standard-conforming compiler) can evaluate it. In C++11, that means that a constexpr function must have a body consisting of a single return-statement (like scale()); in C++14, we can also write simple loops. A constexpr function may not have side effects; that is, it may not change the value of variables outside its own body, except those it is assigned to or uses to initialize.
Here is an example of a function that violates those rules for simplicity:
#include <iostream> int glob = 9; constexpr void bad(int & arg) { // error: no return value ++arg; // error: modifies caller through argument glob = 7; // error: modifies nonlocal variable }
However, this code compiles with gcc 11.2.0:
#include <iostream>
int glob = 9;
int b = 1;
constexpr void bad(int & arg) {
++arg;
glob = 7;
}
int main() {
std::cout << glob << b;
bad(b);
std::cout << glob << b;
}
But I'm not sure why it compiles.
- Is the side-effect allowed in this case because
bad
is being called in non-constant context and therefore behaves like a normal function (as per the first sentence of the quote)? - Has the standard been modified since publication of the book to allow
constexpr
functions to side-effects?
Also, what sort of scenario might the last part of the quote be referring to when it says "uses to initialise"?