0

Playing around with the Compiler Explorer, I can see that GCC can convert even slightly complex functions into constant values at compile time. For example:

int func2(int x, y)
{
    return x ^ y;
}

int func(int x, int y)
{
    int i,j;
    int k=0;

    for (i=0; i<x; i++)
        for (j=0; j<y; j++)
        {
            k += i*j + func2(i,j);
        }
        return k;
}

int main()
{
    int x;
    x = func(4, 7);
    return x;
}

Simply inserts the answer 216 into main's return value. Note that I didn't use the keyword constexpr here. The compiler worked it out itself.

However, according to a few web pages I've read about constexpr, its purpose is to inform the compiler that a compile-time optimisation is possible here, so that the compiler actually bothers to do the calculation at compile time, whereas without the keyword, it wouldn't.

According to this answer on Stackoverflow:

The primary usage of constexpr is to declare intent.

Question:

Does constexpr ever actually change the compiler's output, causing it to calculate something at compile time that it otherwise wouldn't?

Rocketmagnet
  • 5,656
  • 8
  • 36
  • 47
  • 7
    "*According to this answer on Stackoverflow:*" All of the highly voted answers there are just... awful. `constexpr` exists to allow you to generate values which can be consumed by compile-time-only processes (like non-type template parameters). It may be used for other stuff, but that *specifically* is why it needs to be a language feature. – Nicol Bolas Jan 05 '23 at 15:19
  • its for both, its for the programmer to tell the compiler (and other programmers) that the code could be compile time evaluated (and therefore must follow the rules for compile time evaluation) – Alan Birtles Jan 05 '23 at 15:20
  • `int func2(int x, y)` ... I'm surprised this code compiles. – Eljay Jan 05 '23 at 15:23
  • @Eljay - Well spotted. However it does actually compile because C defaults to int if you don't specify a type. – Rocketmagnet Jan 05 '23 at 15:42

1 Answers1

3

When constexpr is applied to a function, it gives permission to use that function in a constant expression. Therefore, if you try to call the function in a context that requires a constant expression, but you have not marked it constexpr, the program will usually not compile.

The usually correct way to think of constexpr is that it's part of the function's interface. If constexpr is absent, it's a hint to the user that even if the function currently doesn't perform any operations that are banned in constant expressions, it is not guaranteed that this will always be the case. Thus, the author of the function has made the wise decision to make your code not compile now if you call the function in a context that requires a constant expression

As for your question of whether constexpr can change the generated machine code: well, if you don't call the function in a context that requires a constant expression, it's up to the compiler whether to evaluate it at compile time anyway. But there are some situations where you can force different behaviour depending on whether constexpr is present: either using SFINAE (see e.g., C++ check if statement can be evaluated constexpr) or std::is_constant_evaluated (which you can usually replace with if consteval in C++23 and later).

Brian Bi
  • 111,498
  • 10
  • 176
  • 312