constexpr specifier (since C++11) - cppreference.com

constexpr - specifies that the value of a variable,

structured binding

(since C++26) or function can appear in

constant expressions

Explanation

The constexpr specifier declares that it is possible to evaluate the value of the entities at compile time. Such entities 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 or non-static member function(until C++14) implies const.

A constexpr specifier used in the first declaration of a function or

static

data member(since C++17) implies inline. If any declaration of a function or function template has a constexpr specifier, then every declaration must contain that specifier.

constexpr variable

A variable or variable template(since C++14) can be declared constexpr if all following conditions are satisfied:

The declaration is a

definition

.

It is of a

literal type

.

It is initialized (by the declaration).

It has constant destruction, which means one of the following conditions needs to be satisfied:

It is not of class type nor (possibly multi-dimensional) array thereof.

It is of a class type with a constexpr destructor or (possibly multi-dimensional) array thereof, and for a hypothetical expression e whose only effect is to destroy the object, e would be a

core constant expression

if the lifetime of the object and its non-mutable subobjects (but not its mutable subobjects) were considered to start within e.

If a constexpr variable is not

translation-unit-local

, it should not be initialized to refer to a translation-unit-local entity that is usable in constant expressions, nor have a subobject that refers to such an entity. Such initialization is disallowed in a

module interface unit

(outside its

private module fragment

, if any) or a module partition, and is deprecated in any other context.

(since C++20)constexpr function

A function or function template can be declared constexpr.

A function is constexpr-suitable if all following conditions are satisfied:

It is not a

virtual

function.

(until C++20)Its return type (if exists) is a

literal type

.

Each of its parameter types is a literal type.

(until C++23)If it is a constructor or destructor(since C++20), extra conditions need to be satisfied (see below).

(until C++26)It is not a

coroutine

.

(since C++20)Its function body is =default, =delete, or a compound statement

enclosing

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 if the function is not a constructor

(until C++14)Its function body is =default, =delete, or a compound statement that(until C++20) does not

enclose

the following:

goto

statements

statements with

labels

other than case and default

definitions of variables of non-literal types

definitions of variables of static or thread

storage duration

(since C++14)
(until C++23)Except for instantiated constexpr functions, non-templated constexpr functions must be constexpr-suitable.

For a non-constructor constexpr function that is neither defaulted nor templated, if no argument values exist such that an invocation of the function could be an evaluated subexpression of a

core constant expression

, the program is ill-formed, no diagnostic required.

For a templated constexpr function, if no specialization of the function/class template would make the templated function constexpr-suitable when considered as a non-templated function, the program is ill-formed, no diagnostic required.

(until C++23)An invocation of a constexpr function in a given context produces the same result as an invocation of an equivalent non-constexpr function in the same context in all respects, with the following exceptions:

An invocation of a constexpr function can appear in a

constant expression

.

Copy elision

is not performed in a constant expression.

constexpr constructor

On top of the requirements of constexpr functions, a constructor also needs to satisfy all following conditions to be constexpr-suitable:

Its function body is =delete or satisfies the following additional requirements:

If the class is a

union

having variant members, exactly one of them is initialized.

If the class is a

union-like class

, but is not a union, for each of its anonymous union members having variant members, exactly one of them is initialized.

Every non-variant non-static data member and base class subobject is initialized.

(until C++20)If the constructor is a

delegating constructor

, the target constructor is a constexpr constructor.

If the constructor is a non-delegating constructor, every constructor selected to initialize non-static data members and base class subobjects is a constexpr constructor.

(until C++23)The class does not have any

virtual base class

.

(until C++26)Constructors do not need to satisfy any extra condition to be constexpr-suitable.

(since C++26)For a constexpr constructor that is neither defaulted nor templated, if no argument values exist such that an invocation of the function could be an evaluated subexpression of the initialization full-expression of some object subject to

constant expression

, the program is ill-formed, no diagnostic required.

(until C++23)constexpr destructor

Destructors cannot be constexpr, but a

trivial destructor

can be implicitly called in constant expressions.

(until C++20)On top of the requirements of constexpr functions, a destructor also needs to satisfy all following conditions to be constexpr-suitable:

For every subobject of class type or (possibly multi-dimensional) array thereof, that class type has a constexpr destructor.

(until C++23)The class does not have any virtual base class.

(since C++20)
(until C++26)Destructors do not need to satisfy any extra condition to be constexpr-suitable.

(since C++26)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:

constexprintf();constexprboolb1=noexcept(f());// false, undefined constexpr functionconstexprintf(){return0;}constexprboolb2=noexcept(f());// true, f() is a constant expression(until C++17)It is possible to write a constexpr function whose invocation can never satisfy the requirements of a core constant expression:

voidf(int&i)// not a constexpr function{i=0;}constexprvoidg(int&i)// well-formed since C++23{f(i);// unconditionally calls f, cannot be a constant expression}(since C++23)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

):

staticconstexprintconst&x=42;// constexpr reference to a const int object// (the object has static storage duration// due to life extension by a static reference)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.

(since C++20)Feature-test macro ValueStdFeature

__cpp_constexpr

200704L

(C++11)constexpr

201304L

(C++14)

Relaxed constexpr

,

non-const constexpr methods

201603L

(C++17)

Constexpr lambda

201907L

(C++20)Trivial

default initialization

and

asm-declaration

in constexpr functions

202002L

(C++20)Changing the active member of a union in constant evaluation

202110L

(C++23)Non-

literal

variables, labels, and

goto

statements in constexpr functions

202207L

(C++23)Relaxing some constexpr restrictions

202211L

(C++23)Permitting staticconstexpr variables in constexpr functions

202306L

(C++26)Constexpr cast from void*: towards constexpr type-erasure

__cpp_constexpr_in_decltype

201711L

(C++11)
(DR)Generation of function and variable definitions when

needed for constant evaluation

__cpp_constexpr_dynamic_alloc

201907L

(C++20)Operations for dynamic storage duration in constexpr functions

__cpp_constexpr_virtual_inheritance

202506L

(C++26)constexpr virtual inheritance Keywords

constexpr

Example

Defines C++11/14 constexpr functions that compute factorials; defines a literal type that extends string literals:

Run this code

#include<iostream>#include<stdexcept>// C++11 constexpr functions use recursion rather than iterationconstexprintfactorial(intn){returnn<=1?1:(n*factorial(n-1));}// C++14 constexpr functions may use local variables and loops#if __cplusplus >= 201402Lconstexprintfactorial_cxx14(intn){intres=1;while(n>1)res*=n--;returnres;}#endif // C++14// A literal classclassconststr{constchar*p;std::size_tsz;public:template<std::size_tN>constexprconststr(constchar(&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 ?:constexprcharoperator[](std::size_tn)const{returnn<sz?p[n]:throwstd::out_of_range("");}constexprstd::size_tsize()const{returnsz;}};// C++11 constexpr functions had to put everything in a single return statement// (C++14 does not have that requirement)constexprstd::size_tcountlower(conststrs,std::size_tn=0,std::size_tc=0){returnn==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 testingtemplate<intn>structconstN{constN(){std::cout<<n<<'\n';}};intmain(){std::cout<<"4! = ";constN<factorial(4)>out1;// computed at compile timevolatileintk=8;// disallow optimization using volatilestd::cout<<k<<"! = "<<factorial(k)<<'\n';// computed at run timestd::cout<<"The number of lowercase letters in \"Hello, world!\" is ";constN<countlower("Hello, world!")>out2;// implicitly converted to conststrconstexprinta[12]={0,1,2,3,4,5,6,7,8};constexprintlength_a=sizeofa/sizeof(int);// std::size(a) in C++17,// std::ssize(a) in C++20std::cout<<"Array of length "<<length_a<<" has elements: ";for(inti=0;i<length_a;++i)std::cout<<a[i]<<' ';std::cout<<'\n';}Output:

4! = 24 8! = 40320 The number of lowercase letters in "Hello, world!" is 9 Array of length 12 has elements: 0 1 2 3 4 5 6 7 8 0 0 0 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 1358

C++11 templated constexpr functions also needed
to have at least one valid argument value no need

CWG 1359

C++11 constexpr union constructors
must initialize all data members initializes exactly one data
member for non-empty unions

CWG 1366

C++11 classes with constexpr constructors whose function bodies
are =default or =delete could have virtual base classes such classes can neither
have virtual base classes

CWG 1595

C++11 constexpr delegating constructors required
all involved constructors to be constexpronly requires the target
constructor to be constexpr

CWG 1712

C++14 a constexpr variable template was required to have
all its declarations contain the constexpr specifier

[1]

not required anymore

CWG 1911

C++11 constexpr constructors for non-literal types were not allowed allowed in constant initialization

CWG 2004

C++11 copy/move of a union with a mutable member
was allowed in a constant expression mutable variants disqualify
implicit copy/move

CWG 2022

C++98 whether equivalent constexpr and non-constexpr
function produce equal result might depend
on whether copy elision is performed assume that copy elision is always
performed in constant expressions

CWG 2163

C++14 labels were allowed in constexpr functions
even though goto statements are prohibited labels also prohibited

CWG 2268

C++11 copy/move of a union with a mutable member was
prohibited by the resolution of

CWG issue 2004

allowed if the object is created
within the constant expression

CWG 2278

C++98 the resolution of

CWG issue 2022

was not implementable assume that copy elision is never
performed in constant expressions

CWG 2531

C++11 a non-inline variable became inline
if it is redeclared with constexprthe variable does
not become inline

It is redundant because there cannot be more than one declaration of a variable template with the constexpr specifier.

See also