Reputation: 3080
I was reading book C++17 - The Complete Guide and in the section 6.1 on constexpr
lambda the author gives two examples:
auto squared1 = [](auto val) constexpr { // example 1. compile-time lambda calls
return val * val;
};
and
constexpr auto squared2 = [](auto val) { // example 2. compile-time initialization
return val * val;
};
and says that these two are different from each other in the sense that example 1 is evaluated at compile time and example 2 is initialized at compile time.
The author then makes the following statements which I don't understand completely:
If (only) the lambda is
constexpr
it can be used at compile time, but If the (closure) object initialized by the lambda isconstexpr
, the object is initialized when the program starts but the lambda might still be a lambda that can only be used at run time (e.g., using static variables). Therefore, you might consider declaring:constexpr auto squared = [](auto val) constexpr { // example 3 return val * val; };
What does the above statement mean exactly?
It is obvious that the constexpr
keyword appears on initialization statement of squared2
lambda object and on the lambda expression itself in example 3 but I don't understand what is the advantage of this over example 1 .
Upvotes: 13
Views: 3186
Reputation: 132260
The thing is, that an auto
-declared object does not adopt the constexpr
'ness of its initializing expression, only its type; and constexpr
is not part of that type. See:
Why does `auto` not adopt the constexpr'ness of its initializing expression?
So, suppose I had:
auto five_squared = 25;
the value 25 is very much constexpr
, i.e. it can be used at compile-time. And yet - five_squared
will not be usable at compile-time. You would still need to indicate it is constexpr
(*).
It's essentially the same with your lambda. A lambda is an instance of an on-the-spot-defined class with an operator()
. Nothing about that would make squared
be a constexpr
variable if you don't make it one yourself.
(*) - Note that because of a special rule in the C++ language, const
integers that are initialized with a constant-expression are automatically constexpr
, so you could just write const auto
and get the constexpr
implicitly. However, this is a tricky special-case to have to remember, so if you want to make a variable constexpr
I recommend being explicit about it. Thanks goes to @cigien for bringing up this point.
Upvotes: 10