constexpr - specifies that the value of a variable or function can appear in constant expressions The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time. Such variables and functions can then be used where only compile time constant expressions are allowed (provided that appropriate function arguments are given). A constexpr specifier used in an object declaration implies const. A constexpr specifier used in a function declaration implies inline.
A constexpr variable must satisfy the following requirements:
LiteralType. constexpr variables and functions. constexpr constructor. In the case of explicit constructor, it must have constexpr specified. A constexpr function must satisfy the following requirements:
LiteralType LiteralType
| (until C++14) |
| (since C++14) |
A constexpr constructor must satisfy the following requirements:
LiteralType.
| (until C++14) |
| (since C++14) |
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:
constexpr int f();
constexpr bool b1 = noexcept(f()); // false, undefined constexpr function
constexpr int f() { return 0; }
constexpr bool b2 = noexcept(f()); // true, f() is a constant expressionConstexpr constructors are permitted for classes that aren't literal types. For example, the default constructor of std::unique_ptr is constexpr, allowing constant initialization.
Definition of a C++11 constexpr function which computes factorials and a literal type that extends string literals:
#include <iostream>
#include <stdexcept>
// C++11 constexpr functions use recursion rather than iteration
// (C++14 constexpr functions may use local variables and loops)
constexpr int factorial(int n)
{
return n <= 1? 1 : (n * factorial(n - 1));
}
// 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 doesn't 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);
}
// 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
}Output:
4! = 24 8! = 40320 the number of lowercase letters in "Hello, world!" is 9
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| CWG 1911 | c++14 | constexpr constructors for non-literal types were not allowed | allowed in constant initialization |
| CWG 2004 | c++14 | assignment of a union with a mutable member was allowed in a constant expression | mutable variants disqualify implicit copy/move |
| CWG 2163 | c++14 | labels were allowed in constexpr functions even though gotos are prohibited | labels also prohibited |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
http://en.cppreference.com/w/cpp/language/constexpr