3

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"?

user51462
  • 1,658
  • 2
  • 13
  • 41
  • 1
    The compiler may have refused to evaluate the function at compile time. `constexpr` does not necessarily mean that it should compute the function at compile time. It's just a hint to the compiler which says "if you can, please evaluate this function at compile time". – Karen Baghdasaryan May 04 '23 at 07:17
  • 2
    Dupe: [Constexpr functions not called at compile-time if result is ignored](https://stackoverflow.com/questions/63422516/constexpr-functions-not-called-at-compile-time-if-result-is-ignored) – Jason May 04 '23 at 07:29
  • 2
    [constexpr functions are allowed to happen at both compile time and run time at the discretion of the compiler.](https://stackoverflow.com/a/8313333/12002570). Another dupe. – Jason May 04 '23 at 07:30
  • 1
    similar to `const` the `constexpr` is a promise by you to the compiler, not the other way around. You declare that the funciton can be evaluated at compile time. You are breaking the promise because it cannot : https://godbolt.org/z/vWf9ex9o7. The compiler will trust in what you say, it will not try to prove you wrong when it isnt necessary (or too difficult in the general case) – 463035818_is_not_an_ai May 04 '23 at 07:32
  • 2
    actually i dont understand your confusion. The quote explains it. "A constexpr function behaves just like an ordinary function until you use it where a constant is needed. " you arent doing that – 463035818_is_not_an_ai May 04 '23 at 07:35
  • Also note that the book is about C++11 and 14. Later revisions of the language, C++17/20/23, have all removed restrictions on constexpr functions. – BoP May 04 '23 at 07:57
  • @463035818_is_not_a_number, I think I misunderstood those "error" annotations in the example code to mean "compile-time error". So, basically the compiler just ignores the `constexpr`? – user51462 May 04 '23 at 08:17
  • I wouldnt say "ignore", it just doesnt make a difference in your code whether it is present or not. – 463035818_is_not_an_ai May 04 '23 at 08:18
  • @463035818_is_not_a_number, just to clarify, does the code in your link fail to compile because `bad` is being called in a place where a constant expression is expected? – user51462 May 04 '23 at 10:05
  • yes. There are different contexts where only a constant expression is ok. I choose a template argument – 463035818_is_not_an_ai May 04 '23 at 10:09
  • @463035818_is_not_a_number so calling a `constexpr` function that contains side-effects will only result in a compile-time error if that function is called in a constant-context; otherwise, it is treated like any other function and the call will be evaluated at run-time. Is this correct? – user51462 May 04 '23 at 10:23
  • please do not use comments for extended discussions. If you have a follow up question you can open a new quesiton (or browse existing ones to see if it has been asked already). This quesiton has been closed as duplicate of other questions, which means the answer should be availble there already (though I didnt check that). The problem with me answering in comments is that I might tell you bulls**t at some point but other than deletion there is no quality assurance of content in comments – 463035818_is_not_an_ai May 04 '23 at 10:27
  • @user51462 Yes only in a `constexpr context` the compiler "must" evaluate it at compile time. Otherwise(meaning in other contexts), it behaves just like a normal/ordinary function. Also read about the [as-if](https://stackoverflow.com/questions/15718262/what-exactly-is-the-as-if-rule) rule. – Jason May 04 '23 at 10:55
  • Thank you, that clears it up. Apologies for asking in the comments. – user51462 May 04 '23 at 11:32

0 Answers0