Hello, 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 becaue 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 fucntion as a constexpr function. A constepxr function can be evaluated at compile time just if it is given constant expressions as arguments.
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:
1 2 3 4 5 6 7 8 9 10
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 is not a constant expression
constexpr Point p6 = scale(p2); // p6 == {100,8};
And here the are my questions :
* Why p2 is considered a constant expression ? I knew that a variable, in this case the p2 data members, cannot be considered a constant expression. Could you please explain me why p2 is considered a constant expression ?
* Can you give me a simple and useful example where I could need to use a constexpr function ?
p2 is not a constant expression.
For it to be usable as a constant expression, we need to write: constexpr Point p2{10,10};
> Can you give me a simple and useful example where I could need to use a constexpr function ?
There are situations in C++ where a constexpr is required: for instance, the size of an array, or a template non-type argument. bool a[ std::numeric_limits<unsignedshort>::max() ] {} ;
@JLBorger Ok. I understand what you're saying, but I still can't understand a thing : the 2 data members of point needs to be constant to be passed to the function scale() ? I don't have the definition of point so I can't see by myself wether they are constant data members or not. Could we pass them to the scale function if they were "simple" data members such as 2 double ?
> I don't have the definition of point so I can't see by myself wether they are constant data members or not.
1 2
// Assume that point is a simple struct with members x and y representing 2D coordinates.
struct Point { double x ; double y ; } ;
> the 2 data members of point needs to be constant to be passed to the function scale() ?
> Could we pass them to the scale function if they were "simple" data members such as 2 double ?
#include <iostream>
// Assume that point is a simple struct with members x and y representing 2D coordinates.
struct Point { double x ; double y ; } ;
constexprdouble xscale = 10; // scaling factors
constexprdouble yscale = 0.8;
constexpr Point scale(Point p) { return { xscale*p.x, yscale*p.y }; }
int main()
{
constexpr Point p1 { 1.2, 3.4 } ; // constexpr
double a, b ;
std::cin >> a >> b ;
const Point p2 { a, b } ; // can't be a constant expression
constexpr Point p3 = scale(p1) ; // constexpr
Point p4 = scale(p2) ; // can't be a constant expression
constexpr Point p5 { p1.x / 2, p3.y * 4 } ; // constexpr
const Point p6 { p1.x / a, p3.y * b } ; // can't be a constant expression
constexpr Point p7 = scale( scale( scale(p1) ) ) ; // constexpr
}
@JLBorges I've got some problem with your code due to a compiler error : p3 illegal initialization of a constexpr entity with a non-constant expression. I also have a warning message about not supported class literal types. Maybe I should update visual studio 2013 ?
Yes. To Visual Studio 2015 (either Community or Desktop).
This may not work in Visual Studio 2015 either, but you should upgrade anyway.
A note about C++11 constexpr: this is a large feature with complicated interactions throughout the Core Language, implemented in a compiler codebase undergoing modernization, being shipped for the first time. It contains bugs/limitations, some of which you might notice, and many of which will be fixed in Updates. ...
Updating to VS 2015 won't help. It chokes on constexpr functions too.
constexprdouble e = exp(1);
compiles just fine with TDM-GCC 4.9.2, but VS 2015 Community errors.
Error C2131 expression did not evaluate to a constant ConsoleApplication1 c:\users\public\documents\my projects\consoleapplication1\consoleapplication1\consoleapplication1.cpp 7
@JLBorges I got some problem if I try to initialize point members's x and y to zero. The compiler segnale an error about constant expression that doesn't return a costant.
Updating to VS 2015 won't help. It chokes on constexpr functions too.
constexpr double e = exp(1);
compiles just fine with TDM-GCC 4.9.2, but VS 2015 Community errors.
gcc 4.9 is wrong: std::exp is not a constexpr function and the standard forbids turning it into constexpr.
clang will tell you:
1 2 3 4 5 6
ain.cpp:3:18: error: constexpr variable 'e' must be initialized by a constant expression
constexprdouble e = exp(1);
^ ~~~~~~
main.cpp:3:22: note: non-constexpr function 'exp' cannot be used in a constant expression
constexprdouble e = exp(1);
^
yes, it applies to all of cmath and yes it's still broken in 5.2 (where "broken" means "proprietary non-portable extension is enabled in strict standard compliance mode")
yes, it applies to all of cmath and yes it's still broken in 5.2 (where "broken" means "proprietary non-portable extension is enabled in strict standard compliance mode")
Now that is something I can understand. It is hard to "get a handle on" the new features when the very tools one uses to learn is non-standard.
Personally I might disagree with that rationale, but I am not on the ISO committee. I have to follow the rules they set up.