首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

constexpr specifier

  • constexpr - specifies that the value of a variable or function can appear in constant expressions

Explanation

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 or static member variable (since C++17) declaration implies inline.

A constexpr variable must satisfy the following requirements:

  • its type must be a LiteralType.
  • it must be immediately initialized
  • the full-expression of its initialization, including all implicit conversions, constructors calls, etc, must be a constant expression

A constexpr function must satisfy the following requirements:

  • it must not be virtual
  • its return type must be LiteralType
  • each of its parameters must be LiteralType
  • there exists at least one set of argument values such that an invocation of the function could be an evaluated subexpression of a core constant expression (for constructors, use in a constant initializer is sufficient) (since C++14). No diagnostic is required for a violation of this bullet.

the function body must be either deleted or defaulted or contain only the following: null statements (plain semicolons) static_assert declarations typedef declarations and alias declarations that do not define classes or enumerations using declarations using directives exactly one return statement.

(until C++14)

the function body must be either deleted or defaulted or contain any statements except: an asm declaration a goto statement a statement with a label other than case and default a try-block a definition of a variable of non-literal type a definition of a variable of static or thread storage duration a definition of a variable for which no initialization is performed. if the function is a defaulted copy/move assignment, the class of which it is a member must not have a mutable variant member

(since C++14)

  • the function body must be either deleted or defaulted or contain only the following:
    • null statements (plain semicolons)
    • static_assert declarations
    • typedef declarations and alias declarations that do not define classes or enumerations
    • using declarations
    • using directives
    • exactly one return statement.

(until C++14)

  • the function body must be either deleted or defaulted or contain any statements except:
    • an asm declaration
    • a goto statement
    • a statement with a label other than case and default
    • a try-block
    • a definition of a variable of non-literal type
    • a definition of a variable of static or thread storage duration
    • a definition of a variable for which no initialization is performed.
  • if the function is a defaulted copy/move assignment, the class of which it is a member must not have a mutable variant member

(since C++14)

A constexpr constructor must satisfy the following requirements:

  • each of its parameters must be LiteralType.
  • the class must have no virtual base classes
  • the constructor must not have a function-try-block

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 every base class and every non-static member must be initialized, either in the constructors initialization list or by a member brace-or-equal initializer. In addition, every constructor involved must be a constexpr constructor and every clause of every brace-or-equal initializer must be a constant expression

(until C++14)

the constructor body must be either deleted or defaulted or satisfy the following constraints: the compound statement of the constructor body must satisfy the constraints for the body of a constexpr function for the constructor of a class or struct, every base class sub-object and every non-variant non-static data member must be initialized. If the class is a union-like class, for each of its non-empty anonymous union members, exactly one variant member must be initialized for the constructor of a non-empty union, exactly one non-static data member must be initialized every constructor selected to initializing non-static members and base class must be a constexpr constructor. if the constructor is a defaulted copy/move constructor, the class of which it is a member must not have a mutable variant member

(since C++14)

  • 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
  • every base class and every non-static member must be initialized, either in the constructors initialization list or by a member brace-or-equal initializer. In addition, every constructor involved must be a constexpr constructor and every clause of every brace-or-equal initializer must be a constant expression

(until C++14)

  • the constructor body must be either deleted or defaulted or satisfy the following constraints:
    • the compound statement of the constructor body must satisfy the constraints for the body of a constexpr function
    • for the constructor of a class or struct, every base class sub-object and every non-variant non-static data member must be initialized. If the class is a union-like class, for each of its non-empty anonymous union members, exactly one variant member must be initialized
    • for the constructor of a non-empty union, exactly one non-static data member must be initialized
    • every constructor selected to initializing non-static members and base class must be a constexpr constructor.
  • if the constructor is a defaulted copy/move constructor, the class of which it is a member must not have a mutable variant member

(since C++14)

For constexpr function templates and constexpr member functions of class templates, at least one specialization must satisfy the abovementioned requirements. Other specializations are still considered as constexpr, even though a call to such a function cannot appear in a constant expression.

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:

代码语言:javascript
复制
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 expression

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

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

代码语言:javascript
复制
static constexpr int const& x = 42; // constexpr reference to a const int object
                                    // (the object has static storage duration
                                    //  due to life extension by a static reference)

Keywords

constexpr.

Example

Definition of a C++11 constexpr function which computes factorials and a literal type that extends string literals:

代码语言:javascript
复制
#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:

代码语言:javascript
复制
4! = 24
8! = 40320
the number of lowercase letters in "Hello, world!" is 9

Defect reports

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

See also

  • constant expression
代码语言:txt
复制
 ? cppreference.com

Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com