Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to understand constexpr in this example?

Tags:

c++

c++17

I'm trying to understand the meaning of constexpr when applied to functions. In the example below the program compiles and runs but I don't understand how the function sum(int n) can be deduced at compile time as n is not known until run time. I'm using VS 2017 with latest updates.

The program compiles whether constexpr is included or not.

#include <iostream>

constexpr int sum(int n)
{    
    return (n <= 0) ? 0 : n + sum(n-1);
}

int main()
{
    int i;
    std::cin >> i;
    std::cout << sum(i) << std::endl;

    return 0;
}

I expected the compiler to error that sum(int n) is not a constant expression. Or is constepxr just a hint to the compiler like "inline", that it is free to ignore?

like image 696
PowerApp101 Avatar asked Dec 13 '25 01:12

PowerApp101


2 Answers

I expected the compiler to error that sum(int n) is not a constant expression.

constexpr int sum(int n); means that the function can be evaluated at compile time. It doesn't have to be. You can call it at runtime without any issues, which makes sense to not force programmers to duplicate code when they need identical functionality at runtime as well as at compile time.

With C++20, you'll be able to trigger the error you were expecting by qualifying the function with the new keyword consteval instead of constexpr.

consteval int sum(int n)
{
    // As before...
}

int i;

// determine i at runtime...

sum(i); // Error! Not evaluated at compile time.

You can have a look at P1073 for this feature. This proposal has been approved for the next standard.

like image 132
lubgr Avatar answered Dec 14 '25 15:12

lubgr


The constexpr keyword says that the function must be evaluated at compile time, if it's called in a constexpr context.

Consider:

constexpr int sum(int n)
{    
    return (n <= 0) ? 0 : n + sum(n-1);
}

int main()
{
    int i;
    std::cin >> i;

    constexpr int s1 = sum(4);        // OK, evaluated at compile time
    int s2 = sum(i);                  // OK, evaluated at run time
    constexpr int s3 = sum(i);        // Error, i cannot be evaluated at compile time
    int s4 = sum(4);                  // OK, execution time depends on the compiler's mood
}

Here, s3 is constexpr and so it's initializer needs to be evaluated at compile time. Hence the error.
If this feature weren't there, you would have to write two versions of your function, one for compile time use and the other for run-time use.
See it yourself on the Compiler Explorer.

Also note that constexpr implies inline for functions.

like image 41
Sam Avatar answered Dec 14 '25 14:12

Sam