I'm new into programming and I started to learn about it using the book Programming principles and practice using C++. Today I'm here because I have some problems in understanding constexpr
functions. In chapter 8 the author introduces them in some lines and a brief example using these words:
A function represents a calculation, and sometimes we want to do a calculation at compile time. The reason to want a calculation evaluated by the compiler is usually to avoid having the same calculation done millions of times at run time.
We convey our intend to have a function evaluated at compile time by declaring the function as a
constexpr
function. Aconstepxr
function can be evaluated at compile time just if it is given constant expressions as arguments.constexpr double xscale = 10; // scaling factors constexpr double yscale = 0.8; constexpr Point scale(Point p) { return { xscale*p.x, yscale*p.y }; };
Assume that point is a simple struct with members x and y representing 2D coordinates. Now, when we give
scale()
aPoint
argument, it returns a point with coordinates scaled according to the factorsxscale
andyscale
. For example:void user(Point p1) { Point p2{10,10}; Point p3 = scale(p1); Point p4 = scale(p2) // p4 == {100,8} constexpr Point p5 = scale(p1); // error : scale(p1) is not a constant expression constexpr Point p6 = scale(p2); // p6 == {100,8};
My question is: Why we can use p2
as an argument to scale()
? Is p2
considered a constant expression? And if yes, why?
Can the data members x
and y
be considered constant expressions?
My book doesn't give too much information so I'm having some problems with this concept.
We allow annotating a function parameter with constexpr with the same meaning as a variable declaration: must be initialized with a constant expression. We add a new keyword, maybe_constexpr , that deduces whether the parameter is known at compile time.
#define directives create macro substitution, while constexpr variables are special type of variables. They literally have nothing in common beside the fact that before constexpr (or even const ) variables were available, macros were sometimes used when currently constexpr variable can be used.
Using constexpr to Improve Security, Performance and Encapsulation in C++ 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.
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).
Basically, constexpr
functions can be executed at compile time or run time depending on the context. It is guaranteed to execute at compile time only if all its parameters are constexpr
and its result is used in a context requiring constexpr
(e.g. assignment to constexpr
value, template parameter, or, say, c-style array size). Otherwise, it is evaluated at runtime as any other function. So the p3
and p4
lines are executed at runtime, whereas p5
gives an error because scale(p1)
is not constexpr
, and actually p6
should also give you an error unless you add a constexpr
to the definition of p2
. See an example here.
It looks to me, that it's gotcha in book. It looks like it should be
constexpr Point p2{10,10};
only in this case any modern compiler will not give error on call
constexpr Point p6 = scale(p2); // p6 == {100,8};
that's because you are trying to initialize constexpr
variable with result of function, which will be evaluated in runtime (if p2
is not declared constexpr
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With