Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/language/constexpr"

From cppreference.com
< cpp‎ | language
m (r2.7.3) (Robot: Adding de, es, fr, it, ja, pt, ru, zh)
(example should be more obvious now)
Line 86: Line 86:
 
     constN<factorial(4)> out1; // computed at compile time
 
     constN<factorial(4)> out1; // computed at compile time
  
     volatile int k = 8;
+
     volatile int k = 8; // disallow optimization using volatile
 
     std::cout << k << "! = " << factorial(k) << '\n'; // computed at run time
 
     std::cout << k << "! = " << factorial(k) << '\n'; // computed at run time
  

Revision as of 11:28, 12 January 2013

 
 
C++ language
General topics
Flow control
Conditional execution statements
if
Iteration statements (loops)
for
range-for (C++11)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications (until C++17*)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
explicit (C++11)
static

Special member functions
Templates
Miscellaneous
 
  • constexpr - specifies that the value of a variable or function can be computed at compile time

Explanation

constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time, they then can be used where only compile time constant expressions are allowed. constexpr implies const.

constexpr variables must satisfy the following requirements:

  • it must be immediately constructed or assigned a value.
  • the constructor parameters or the value to be assigned must contain only literal values, constexpr variables and functions.
  • the constructor used to construct the object (either implicit or explicit) must satisfy the requirements of constexpr constructor. In the case of explicit constructor, it must have constexpr specified.

constexpr functions must satisfy the following requirements:

  • it must not be virtual
  • its return type must be Template:concept
  • each of its parameters must be literal type
  • the function body must be either deleted or defaulted or contain only the following:
  • null statements
  • static_assert declarations
  • typedef declarations and alias declarations that do not define classes or enumerations
  • using declarations
  • using directives
  • exactly one return statement that contains only literal values, constexpr variables and functions.

constexpr constructor must satisfy the following requirements:

  • each of its parameters must be literal type
  • the class must have no virtual base classes
  • the constructor body must be either deleted or defaulted or contain only the following:
  • null statements
  • static_assert declarations
  • typedef declarations and alias declarations that do not define classes or enumerations
  • using declarations
  • using directives
  • the constructor must not have a function-try block
  • every base class and every non-static member must be initialized, either in the initializer_list or by brace-or-equal initializer. End every constructor involved must be a constexpr constructor and every clause of every brace-or-equal initializer must be a constant expression
  • every implicit conversion involved must be a constant expression

Keywords

constexpr

Example

Definition of a constexpr function which computes factorials and a literal type that extends string literals

#include <iostream>
#include <stdexcept>
 
// constexpr functions use recursion rather than iteration
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 from operator ?:
    constexpr char operator[](std::size_t n) {
        return n < sz ? p[n] : throw std::out_of_range("");
    }
    constexpr std::size_t size() { return sz; }
};
constexpr std::size_t countlower(conststr s, std::size_t n = 0,
                                             std::size_t c = 0) {
    return n == s.size() ? c :
           s[n] >= 'a' && 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 << "Number of lowercase letters in \"Hello, world!\" is ";
    constN<countlower("Hello, world!")> out2; // implicitly converted to conststr
}

Output:

4! = 24
8! = 40320
Number of lowercase letters in "Hello, world!" is 9