Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing arguments to constexpr functions

Tags:

c++

constexpr

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. A constepxr 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() a Point argument, it returns a point with coordinates scaled according to the factors xscale and yscale. 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.

like image 334
piero borrelli Avatar asked Aug 27 '15 11:08

piero borrelli


People also ask

Can a function parameter be constexpr?

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.

When to use #define vs constexpr?

#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.

Does constexpr improve performance?

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.

What does constexpr mean in C++?

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).


2 Answers

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.

like image 83
Rostislav Avatar answered Oct 21 '22 06:10

Rostislav


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).

like image 39
ForEveR Avatar answered Oct 21 '22 06:10

ForEveR