constexpr in C++ explained in detail

Share the Article

The constexpr is a keyword present in C++11. This keyword indicates a constant value or a constant expression during the compilation phase. The constexpr is used with both variables as well as with functions.

The use of constexpr causes compiler to evaluate an expression at compile time. This expression then becomes a constant value at run-time.

This means, if the program uses constexpr in a variable definition, then it becomes a constant variable. And, consequently, when the program uses constexpr with an expression or function then compiler executes it to create a final contant value. However, it should be noted that all the inputs of a constexpr function must be known at compilation.

Since, the use of constexpr causes compiler to replace expressions with a constant, therefore, use of constexpr leads to improvement in run-time performance.

Basic example – calling constexpr function to set a constexpr variable

In following example, the variable “iy” is constexpr. The value of “iy” is based on function “permuation”, which is also a contexpr function. And, since, the input of permutation is known at compile time (const int ix=6), therefore, compiler shall execute this function during compilation and generate a constant value.

#include <iostream> //main header using namespace std; //namespace constexpr int permutation(int N) { return (N?N*permutation(N-1):1); } int main() { const int ix=6; constexpr int iy = permutation(x); cout << iy << endl; return 0; }

Using Non-constexpr function with constexpr variable

C++ compiler evaluates only those functions in compilation which are declared as constexpr. In the following example, even though the input of function “permutation” is compile-time constant, but this will not compile to assign value to variable “iy”. The compile-time evaluation cannot happen in absence of constexpr keyword.

#include <iostream> //main header using namespace std; //namespace int permutation(int N) //No constexpr { return (N?N*permutation(N-1):1); } int main() { const int ix=6; constexpr int iy = permutation(ix); cout << iy << endl; return 0; }

The above program shall generate following error during compilation.

compiler error by calling non-const function in constexpr

All Literal types can be constexpr

In C++11, all built-in types except “void” qualify to become contexpr. Same rule will apply for user-defined types, because constructors and other member functions may be constexpr

Passing non-constant input to constexpr function

A constexpr function only expects a contant input during compilation phase. In the following example, program uses a variable “ix” to provide an input. This is wrong because technically the value “ix” can change anytime.

#include <iostream> //main header using namespace std; //namespace constexpr int permutation(int N) { return (N?N*permutation(N-1):1); } int main() { int ix=3; //ix is not constant constexpr int iy = permutation(ix); cout << iy << endl; return 0; }

The compiler shall throw following error and cause compilation to stop.

using non-const argument in constexpr expression

Using constexpr function with (non-constexpr) variable

The program can use a contexpr function even for non-constexpr variables. In such cases, the compiler shall not evaluate any value at compile-time, but these will be used just like normal functions.

#include <iostream> //main header using namespace std; //namespace constexpr int permutation(int N) //constexpr { return (N?N*permutation(N-1):1); } int main() { int ix; int iy = permutation(ix); //y is not const cout << iy << endl; return 0; }

The above program shall compile but y will not be a compile time constant.

Only one return-line statement in C++11

In C++11, a constexpr function can have only one single return-line statement. The compiler shall throw an error if multiple lines are present. This limitation is not in C++14. The following program shall compile in C++14 but not in C++11.

#include <iostream> //main header using namespace std; //namespace constexpr int permutation(int N) //multiple lines { if(!N) return 1; return N * permutation(N-1); } int main() { constexpr int ix = 6; constexpr int iy = permutation(ix); cout << iy << endl; return 0; }

C++11 compiler shall throw following error:

one line return statement in constexpr function in c++11

constexpr as constructor

A constructor can also be of type contexpr. This means, if the program creates an object, then constructor code shall run at compile-time.

In the following example, the constructor is accepting an integer parameter. Since, the constructor argument value is constant therefore, the compiler shall construct the object during compilation. Finally, the object which is created will be a constant object.

#include <iostream> //main header using namespace std; //namespace class MainFunda { int ival; public: constexpr MainFunda(int ip) : ival(ip) { } void printAddress() const { cout << "The address at runtime is : " << &ival << endl; } }; int main() { constexpr MainFunda oa(4); //Constant object (in C++11) oa.printAddress(); return 0; }

Output is:

The address at runtime is : 0x7ffd000b577c

Please note that the constructor do not have any code in the definition. If constructor has some statement which can be executed only in run-time, then compiler shall throw an error.

constexpr MainFunda(int ip) : ival(ip) { cout << "This is constructor"; //This cannot execute }

The compiler will generate following error

contexpr constructor for  construction with C+11

In C++11, constexpr object can’t modify the object

Please note that in above example, the function printAddress is declared as const. This is because the object “a” that was created will be a constant.

There are 2 restrictions in C++11.

Firstly, any constexpr member functions implicitly become constant functions. Therefore, a non-constant object cannot call such member functions.

Secondly, a member function with void return type cannot become constexpr. This is because void is not a literal type in C++11.

Both these restrictions are lifted in C++14,

#include <iostream> //main header using namespace std; //namespace class MainFunda { int ival; public: constexpr MainFunda(int ip) : ival(ip) { } constexpr void setValue(int iv) //void return invalid { ival = iv; //Modify the object } }; int main() { MainFunda a2(4); a2.setValue(5); return 0; }

The above program shall compile in C++14 but give out following error in C++11. This cause following 2 errors to be thrown.

contexpr constructor for  construction with C+14

Main Funda: contexpr causes compiler to execute code during compilation

Related Topics:

 What are the drawbacks of using enum ?
Which member functions are generated by compiler in class?
How to stop compiler from generating special member functions?
Compiler Generated Destructor is always non-virtual
How to make a class object un-copyable?
Why virtual functions should not be called in constructor & destructor ?
Explaining C++ casts
How pointer to class members are different ?
How std::forward( ) works?
Rule of Three
How std::move() function works?
What is reference collapsing?
How delete keyword can be used to filter polymorphism
emplace_back vs push_back


Share the Article

Leave a Reply

Your email address will not be published. Required fields are marked *