template<int N>class fixed_size_list{ /*...*/ };
fixed_size_list<X> mylist; // X must be an integer constant expression
int numbers[X]; // X must be an integer constant expression
template<int N>class list{ };
constexpr int sqr1(int arg){ return arg * arg; }
int sqr2(int arg){ return arg * arg; }
int main(){const int X = 2;list<sqr1(X)> mylist1; // OK: sqr1 is constexprlist<sqr2(X)> mylist2; // wrong: sqr2 is not constexpr}
const int dmv = 17; // dmv is a named constantint var = 17; // var is not a constantconstexpr double max1 = 1.4*square(dmv); // OK if square(17) is a constant expressionconstexpr double max2 = 1.4∗square(var); // error : var is not a constant expressionconst double max3 = 1.4∗square(var); //OK, may be evaluated at run timedouble sum(const vector<double>&); // sum will not modify its argument (§2.2.5)vector<double> v {1.2, 3.4, 4.5}; // v is not a constantconst double s1 = sum(v); // OK: evaluated at run timeconstexpr double s2 = sum(v); // error : sum(v) not constant expression
int arr[mx]; // error: “constant expression required”
constexpr is a new C++11 keyword that rids you of the need to create macros and hardcoded literals. It also guarantees, under certain conditions, that objects undergo static initialization. It controls the evaluation time of an expression. By enforcing compile-time evaluation of its expression, constexpr lets you define true constant expressions that are crucial for time-critical applications, system programming, templates, and generally speaking, in any code that relies on compile-time constants.
Constant-expression functions
A constant-expression function is a function declared constexpr. Its body must be non-virtual and consist of a single return statement only, apart from typedefs and static asserts. Its arguments and return value must have literal types. It can be used with non-constant-expression arguments, but when that is done the result is not a constant expression.
A constant-expression function is meant to replace macros and hardcoded literals without sacrificing performance or type safety.
constexpr int max() { return INT_MAX; } // OKconstexpr long long_max() { return 2147483647; } // OKconstexpr bool get_val(){bool res = false;return res;} // error: body is not just a return statement
constexpr int square(int x){ return x * x; } // OK: compile-time evaluation only if x is a constant expressionconst int res = square(5); // OK: compile-time evaluation of square(5)int y = getval();int n = square(y); // OK: runtime evaluation of square(y)
struct S{constexpr int two(); // constant-expression functionprivate:static constexpr int sz; // constant-expression object};constexpr int S::sz = 256;enum DataPacket{Small = S::two(), // error: S::two() called before it was definedBig = 1024};constexpr int S::two() { return sz*2; }constexpr S s;int arr[s.two()]; // OK: s.two() called after its definition
constexpr int var不能在运行时动态设置,而是在编译时动态设置。一旦它设置为该值,就不能再更改它。
这里有一个坚实的例子:
int main(int argc, char*argv[]) {const int p = argc;// p = 69; // cannot change p because it is a const// constexpr int q = argc; // cannot be, bcoz argc cannot be computed at compile timeconstexpr int r = 2^3; // this works!// r = 42; // same as const too, it cannot be changed}
int temp=rand(); // temp is generated by the the random generator at runtime.
const int x1=10; // OK - known at compile time.const int x2=temp; // OK - known only at runtime.constexpr int x3=10; // OK - known at compile time.constexpr int x4=temp; // ERROR. Compiler can't figure out the value of 'temp' variable at compile time so `constexpr` can't be applied here.
int temp=rand(); // temp is generated by the the random generator at runtime.
int array1[10]; // OK.int array2[temp]; // ERROR.
所以这意味着:
const int size1=10; // OK - value known at compile time.const int size2=temp; // OK - value known only at runtime.constexpr int size3=10; // OK - value known at compile time.
int array3[size1]; // OK - size is known at compile time.int array4[size2]; // ERROR - size is known only at runtime time.int array5[size3]; // OK - size is known at compile time.
constexpr int func_constexpr(int X, int Y){return(X*Y);}
int func(int X, int Y){return(X*Y);}
int array1[func_constexpr(10,20)]; // OK - func_constexpr() can be evaluated at compile time.int array2[func(10,20)]; // ERROR - func() is not a constexpr function.
int array3[func_constexpr(10,rand())]; // ERROR - even though func_constexpr() is the 'constexpr' function, the expression 'constexpr(10,rand())' can't be evaluated at compile time.
int value1=func_constexpr(10,rand()); // OK. value1 is non-constexpr value that is evaluated in runtime.constexpr int value2=func_constexpr(10,rand()); // ERROR. value2 is constexpr and the expression func_constexpr(10,rand()) can't be evaluated at compile time.
constexpr也可以应用于成员函数(方法)、运算符甚至构造函数。例如。
class test2{static constexpr int function(int value){return(value+1);}
void f(){int x[function(10)];
}};
一个更“疯狂”的样本。
class test3{public:
int value;
// constexpr const method - can't chanage the values of object fields and can be evaluated at compile time.constexpr int getvalue() const{return(value);}
constexpr test3(int Value): value(Value){}};
constexpr test3 x(100); // OK. Constructor is constexpr.
int array[x.getvalue()]; // OK. x.getvalue() is constexpr and can be evaluated at compile time.
#include<iostream>constexpr int multiply (int x, int y){
return x * y;}
extern const int val = multiply(10,10);int main () {std::cout << val;}
编译成
val:.long 100 //extra external definition supplied due to extern
main:push rbpmov rbp, rspmov esi, 100 //substituted in as an immediatemov edi, OFFSET FLAT:_ZSt4coutcall std::basic_ostream<char, std::char_traits<char> >::operator<<(int)mov eax, 0pop rbpret
__static_initialization_and_destruction_0(int, int):...
然而
#include<iostream>const int multiply (int x, int y){
return x * y;}
const int val = multiply(10,10); //constexpr is an errorint main () {std::cout << val;}
constexpr int square (int a){return a*a;}
constexpr int a = 3;constexpr int b = 5;
int arr[square(a*b+20)] = {0}; //This expression is equal to int arr[35] = {0};