constexpr specifier (since C++11)

constexpr - specifies that the value of a variable, structured binding(since C++26) or function can appear in constant expressions

# Notes

Because the noexcept operator always returns true for a constant expression, it can be used to check if a particular invocation of a constexpr function takes the constant expression branch:

It is possible to write a constexpr function whose invocation can never satisfy the requirements of a core constant expression:

Constexpr constructors are permitted for classes that are not literal types. For example, the default constructor of std::shared_ptr is constexpr, allowing constant initialization.

Reference variables can be declared constexpr (their initializers have to be reference constant expressions):

Even though try blocks and inline assembly are allowed in constexpr functions, throwing exceptions that are uncaught(since C++26) or executing the assembly is still disallowed in a constant expression.

If a variable has constant destruction, there is no need to generate machine code in order to call destructor for it, even if its destructor is not trivial.

A non-lambda, non-special-member, and non-templated constexpr function cannot implicitly become an immediate function. Users need to explicitly mark it consteval to make such an intended function definition well-formed.

# Example

#include <iostream>
#include <stdexcept>
 
// C++11 constexpr functions use recursion rather than iteration
constexpr int factorial(int n)
{
    return n <= 1 ? 1 : (n * factorial(n - 1));
}
 
// C++14 constexpr functions may use local variables and loops
#if __cplusplus >= 201402L
constexpr int factorial_cxx14(int n)
{
    int res = 1;
    while (n > 1)
        res *= n--;
    return res;
}
#endif // C++14
 
// A literal class
class conststr
{
    const char* p;
    std::size_t sz;
public:
    template<std::size_t N>
    constexpr conststr(const char(&a)[N]): p(a), sz(N - 1) {}
 
    // constexpr functions signal errors by throwing exceptions
    // in C++11, they must do so from the conditional operator ?:
    constexpr char operator[](std::size_t n) const
    {
        return n < sz ? p[n] : throw std::out_of_range("");
    }
 
    constexpr std::size_t size() const { return sz; }
};
 
// C++11 constexpr functions had to put everything in a single return statement
// (C++14 does not have that requirement)
constexpr std::size_t countlower(conststr s, std::size_t n = 0,
                                             std::size_t c = 0)
{
    return n == s.size() ? c :
        'a' <= s[n] && s[n] <= 'z' ? countlower(s, n + 1, c + 1)
                                   : countlower(s, n + 1, c);
}
 
// An output function that requires a compile-time constant, for testing
template<int n>
struct constN
{
    constN() { std::cout << n << '\n'; }
};
 
int main()
{
    std::cout << "4! = ";
    constN<factorial(4)> out1; // computed at compile time
 
    volatile int k = 8; // disallow optimization using volatile
    std::cout << k << "! = " << factorial(k) << '\n'; // computed at run time
 
    std::cout << "The number of lowercase letters in \"Hello, world!\" is ";
    constN<countlower("Hello, world!")> out2; // implicitly converted to conststr
 
    constexpr int a[12] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
    constexpr int length_a = sizeof a / sizeof(int); // std::size(a) in C++17,
                                                      // std::ssize(a) in C++20
    std::cout << "Array of length " << length_a << " has elements: ";
    for (int i = 0; i < length_a; ++i)
        std::cout << a[i] << ' ';
    std::cout << '\n';
}

# Defect reports

DRApplied toBehavior as publishedCorrect behavior
CWG 1358C++11templated constexpr functions also neededto have at least one valid argument valueno need
CWG 1359C++11constexpr union constructorsmust initialize all data membersinitializes exactly one datamember for non-empty unions
CWG 1366C++11classes with constexpr constructors whose function bodiesare = default or = delete could have virtual base classessuch classes can neitherhave virtual base classes
CWG 1595C++11constexpr delegating constructors requiredall involved constructors to be constexpronly requires the targetconstructor to be constexpr
CWG 1712C++14a constexpr variable template was required to haveall its declarations contain the constexpr specifier[1]not required anymore
CWG 1911C++11constexpr constructors for non-literal types were not allowedallowed in constant initialization
CWG 2004C++11copy/move of a union with a mutable memberwas allowed in a constant expressionmutable variants disqualifyimplicit copy/move
CWG 2022C++98whether equivalent constexpr and non-constexprfunction produce equal result might dependon whether copy elision is performedassume that copy elision is alwaysperformed in constant expressions
CWG 2163C++14labels were allowed in constexpr functionseven though goto statements are prohibitedlabels also prohibited
CWG 2268C++11copy/move of a union with a mutable member wasprohibited by the resolution of CWG issue 2004allowed if the object is createdwithin the constant expression
CWG 2278C++98the resolution of CWG issue 2022 was not implementableassume that copy elision is neverperformed in constant expressions
CWG 2531C++11a non-inline variable became inlineif it is redeclared with constexprthe variable doesnot become inline

# See also