In C++11, is "lambda function" same with "lambda expression" and "closure"? - c++

On cppreference website,when talking about direct_initialization, it says it works in closure parameter capture like...{...}
I think this should be "lambda function", but why it's also called "closure"?
I checked C++11 standard, the item "closure" first appeared in section 5.1.2 (lambda expression),which says:
The evaluation of a lambda-expression results in a prvalue temporary (12.2). This temporary is called the
closure object. A lambda-expression shall not appear in an unevaluated operand (Clause 5). [ Note: A
closure object behaves like a function object (20.8). — end note ]
So how to understand "evalute lamdba expression"? It this "evaluation" something happened during compilation or runtime?
Is there differences in C++11, among the items "lambda expression", "lambda function", and "closure"?
I'm not talking about other programming languages like Closure, just focus on C++11.
Thanks.

What is a closure (quoting from wikipedia):
In programming languages, closures (also lexical closures or function
closures) are a technique for implementing lexically scoped name
binding in languages with first-class functions. Operationally, a
closure is a record storing a function[a] together with an
environment: a mapping associating each free variable of
the function (variables that are used locally, but defined in an
enclosing scope) with the value or storage location to which the name
was bound when the closure was created[b]. A closure,
unlike a plain function, allows the function to access those captured
variables through the closure's reference to them, even when the
function is invoked outside their scope.
[a] The function may be stored as a reference to a function,
such as a function pointer.
[b] These names most frequently refer to values, mutable
variables, or functions, but can also be other entities such as
constants, types, classes, or labels.
What is a lambda expression (quoting from wikipedia):
In computer programming, an anonymous function (function literal,
lambda abstraction) is a function definition that is not bound to an
identifier.
Since C++11, C++ supports anonymous functions, called lambda
expressions, which have the form:
[capture](parameters) -> return_type { function_body }
An example lambda function is defined as follows:
[](int x, int y) -> int { return x + y; }
Since C++11, C++ also supports closures. Closures are defined between
square brackets [and] in the declaration of lambda expression. The
mechanism allows these variables to be captured by value or by
reference. The following table demonstrates this:
[] //no variables defined. Attempting to use any external variables in the lambda is an error.
[x, &y] //x is captured by value, y is captured by reference
[&] //any external variable is implicitly captured by reference if used
[=] //any external variable is implicitly captured by value if used
[&, x] //x is explicitly captured by value. Other variables will be captured by reference
[=, &z] //z is explicitly captured by reference. Other variables will be captured by value
Résumé
Terms Lambda expression and Lambda function are used interchangeably for signifying the definition/declaration of an anonymous function object as:
[capture](parameters) -> return_type { function_body }
With the term closure we refer to the run-time function object created by the evaluation of a lambda expression.
Now for lambdas to be evaluated at compile time, this would require a lambda to be a constant expression. Unfortunately, lambdas aren't constexpr and as such can't be evaluated at compile time. However, there's a proposal submitted to the committee N4487 that suggests that with the lifting of some restrictions we could have constexpr lambdas. That is, in the future we might have constexpr lambdas that could be evaluated at compile time.

Lambda expression is like other expressions, being evaluated at runtime by default. Evaluating the expression 1 + 2 gives a int which value is 3. Evaluating the lambda expression [] { return 0; } gives a closure object, which is also a function object, which operator()() is a function that returns 0.
In short, a closure object is a runtime object, like any other objects in C++, a lambda expression is a expression which result is a closure object.

Related

Why can't I use constexpr with lambda function?

I need an explanation for this. How does lambda differ from others function to it don't be allowed? Is this a nonsense to be not part of C++ standard? for example, I wanted to write a "nested" function in C++ but like it isn't possible to do directly I do use lambda instead of. This function does a very small job: take a single int parameter and multiply with some values and returns. This values are locals to where lambda function is defined and all them are constexpr and know at run-time for this reason I do want to let the compiler put a const value instead of call the function. It's very often used function (that's why I write this as function) and I don't want this beging computed at run-time.
It is because the standard list lambda as non constant expression : "5.19 Constant expressions" … "is a core constant expression unless it involves one of the following as a potentially evaluated subexpression" … "— a lambda-expression (5.1.2);"
That is enough for any compiler to reject constexpr function with a lambda involved.

Why are lambda expressions not allowed in an unevaluated operands but allowed in the unevaluated portions of constant expressions?

If we look at the draft C++ standard section 5.1.2 Lambda expressions paragraph 2 says (emphasis mine going forward):
The evaluation of a lambda-expression results in a prvalue temporary (12.2). This temporary is called the closure object. A lambda-expression shall not appear in an unevaluated operand (Clause 5). [ Note: A closure object behaves like a function object (20.8).—end note ]
and section 5.19 Constant expressions paragraph 2 says:
A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression (3.2), but subexpressions of logical AND (5.14), logical OR (5.15), and conditional (5.16) operations that are not evaluated are not considered [...]
and has the following bullet:
— a lambda-expression (5.1.2);
So why are lambdas expressions not allowed in an unevaluated operand but are allowed in the unevaluated portions of constant expressions?
I can see how for unevaluated operands the type information in several cases(decltype or typeid) is not very useful since each lambda has a unique type. Although why we would want to allow them in the unevaluated context of a constant expression is not clear, perhaps to allow for SFINAE?
The core reason for the unevaluated operands exclusion is covered in C++ Standard Core Language Defect Reports and Accepted Issues #1607. Lambdas in template parameters which seeks to clarify this restriction and states the intention of the restriction in section 5.1.2 was to:
[...] avert the need to deal with them in function template signatures [...]
As the issue documents the current wording actually has a hole since constant expressions allows them in an unevaluated context. But it does not outright state the rationale for this restriction. The desire to avoid name mangling stands out and you can infer that avoiding extending SFINAE was also desired since the proposed resolution seeks to tighten the restriction even though several viable alternatives would have allowed SFINAE. The modified version of 5.1.2 paragraph 2 as follows:
A lambda-expression shall not appear in an unevaluated operand (Clause 5 [expr]), in a template-argument, in an alias-declaration, in a typedef declaration, or in the declaration of a function or function template outside its function body and default arguments [Note: The intention is to prevent lambdas from appearing in a signature —end note]. [Note: A closure object behaves like a function object (20.10 [function.objects]). —end note]
This proposal was accepted and is in N3936(see this answer for a link)
For a more explicit discussion of the rationale to avoid having lambdas as an unevaluated operand. The discussion titled Rationale for lambda-expressions not being allowed in unevaluated contexts on comp.lang.cpp.moderated Daniel Krügler lays out three reasons:
The extreme extension of possible SFINAE cases :
[...]The reason why they became excluded was due to exactly this extreme extension of sfinae cases (you were opening a Pandora box for the compiler)[...]
In many cases it is just useless since each lambda has a unique type, the hypothetical example given:
template<typename T, typename U>
void g(T, U, decltype([](T x, T y) { return x + y; }) func);
g(1, 2, [](int x, int y) { return x + y; });
The type of the lambda in the declaration and the call are different(by definition) and therefore this can not work.
Name mangling also becomes a problem since once you allow a lambda in a function signature the bodies of the lambda will have to be mangled as well. This means coming up with rules to mangle every possible statement, which would burdensome for at least some implementations.

Access C++14 lambda captures like struct members

AFAIK, C++11/14 does not allow in-place definition of a new return type while defining a lambda. However, it seems a C++14 lambda capture expression essentially creates an anonymous type with one or more "members" and an operator (). So, why is that the compiler does not allow access to the captured members from outside the lambda. My feeble mind cannot handle the complexities of C++ but does it sound like a reasonable language extension to you? Here is an example.
vector<string> words = { "Stack", "Overflow" };
auto l = [w = words](){}; // almost like a C# anonymous type
cout << l.w[0]; // does not work.
The status quo
This was discussed when lambda init-captures were added to the language. The current working draft of the standard (N3797) says (in [expr.prim.lambda]p11):
For every init-capture a non-static data member named by the identifier of the init-capture is declared in the closure type.
The standard does not specify the access of that member, making it unclear whether this is valid:
auto x = [n(0)] {};
int k = x.n; // ok?
This and some other specification problems with init-captures led to national body comment GB3 on the standard draft, which is handled by the C++ core working group as core issue 1760. In discussion of that issue, the core working group decided that the lambda's init-captures should not be accessible members of the closure object.
The resolution for issue 1760 (which is approved by CWG but not yet by the full committee) changes the specification to instead say:
An init-capture behaves as if it declares and explicitly captures a variable of the form “auto init-capture ;” whose declarative region is the lambda-expression's compound-statement [...]
This new wording makes it clear that the init-capture does not add a nameable member of the closure object, and it instead acts like any other lambda capture.
As a language extension
Making init-captures be accessible members of the closure type is certainly possible (and my initial implementation of init-captures in clang did that, before I implemented the resolution of issue 1760). It also seems like a useful feature, but it would also allow violation of the encapsulation of lambda-expressions in the common case where the init-captures should not be visible.
If I'm understanding this right, you want to be able to access a variable that is captured within a lambda. But according to the top answer on Get captured variables from lambda?, it's not possible.
It's not possible by design
5.1.2 [expr.prim.lambda]
15 [...] For each entity captured by copy, an unnamed non-static data member is declared in the closure type. The declaration order of these members is unspecified. [...]
16 [...] It is unspecified whether additional unnamed non-static data members are
declared in the closure type for entities captured by reference.
Captured variables are unnamed (or at least have names that are
unspeakable by mortals) and their declaration order is deliberately
unspecified. By-reference captures may not even exist in the closure
type.
Bold emphasis mine.

What am I allowed to do with a static, constexpr, in-class initialized data member?

This is probably a bit of an unusual question, in that it asks for a fuller explanation of a short answer given to another question and of some aspects of the C++11 Standard related to it.
For ease of reference, I shall sum up the referenced question here. The OP defines a class:
struct Account
{
static constexpr int period = 30;
void foo(const int &) { }
void bar() { foo(period); } //no error?
};
and is wondering why he gets no error about his usage of an in-class initialized static data member (a book mentioned this to be illegal). Johannes Schaub's answer states, that:
This violates the One Definition Rule;
No diagnostics is required.
As much as I rely the source and validity of this answer, I honestly dislike it because I personally find it too cryptic, so I tried to work out a more meaningful answer myself, with only partial success. Relevant seems to be § 9.4.2/4:
"There shall be exactly one definition of a static data member that is odr-used (3.2) in a program; no diagnostic is required" [Emphases are mine]
Which gets me a bit closer to the point. And this is how § 3.2/2 defines an odr-used variable:
"A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) is immediately applied" [Emphases are mine]
In the OP's question, variable period clearly satisfies the requirements for appearing in a constant expression, being a constexpr variable. So the reason must be certainly found in the second condition: "and the lvalue-to-rvalue conversion (4.1) is immediately applied".
This is where I have troubles interpreting the Standard. What does this second condition actually mean? What are the situations it covers? Does it mean that a static constexpr variable is not odr-used (and therefore can be in-class initialized) if it is returned from a function?
More generally: What are you allowed to do with a static constexpr variable so that you can in-class initialize it?
Does it mean that a static constexpr variable is not odr-used (and
therefore can be in-class initialized) if it is returned from a
function?
Yes.
Essentially, as long as you treat it as a value, rather than an object, then it is not odr-used. Consider that if you pasted in the value, the code would function identically- this is when it is treated as an rvalue. But there are some scenarios where it would not.
There are only a few scenarios where lvalue-to-rvalue conversion is not performed on primitives, and that's reference binding, &obj, and probably a couple others, but it's very few. Remember that, if the compiler gives you a const int& referring to period, then you must be able to take it's address, and furthermore, this address must be the same for each TU. That means, in C++'s horrendous TU system, that there must be one explicit definition.
If it is not odr-used, the compiler can make a copy in each TU, or substitute the value, or whatever it wants, and you can't observe the difference.
You missed a part of the premise. The class definition give above is completely valid, if you also define Account::period somewhere (but without providing an initializer). See the last sentance of 9.4.2/3:
The member shall still be defined in a namespace scope if it is odr-used
(3.2) in the program and the namespace scope definition shall not
contain an initializer.
This entire discussion only applies to static constexpr data members, not to namespace-scope static variables. When static data members are constexpr (rather than simply const) you have to initialize them in the class definition. So your question should really be: What are you allowed to do with a static constexpr data member so that you don't have to provide a definition for it at namespace scope?
From the preceding, the answer is that the member must not be odr-used. And you already found relevant parts of the definition of odr-used. So you can use the member in a context where it is not potentially-evaluated - as an unevaluated operand (for example of sizeofor decltype) or a subexpression thereof. And you can use it in an expression where the lvalue-to-rvalue conversion is immediately applied.
So now we are down to What uses of a variable cause an immediate lvalue to rvalue conversion?
Part of that answer is in §5/8:
Whenever a glvalue expression appears as an operand of an operator
that expects a prvalue for that operand, the lvalue-to-rvalue (4.1),
array-to-pointer (4.2), or function-to-pointer (4.3) standard
conversions are applied to convert the expression to a prvalue.
For arithmetic types that essentially applies to all operators that apply standard arithmetic conversions. So you can use the member in various arithmetic and logical operations without needing a definition.
I can't enumerate all things, you can or can't do here, because the requirements that something be a [g]lvalue or [p]rvalue are spread across the standard. The rule of thumb is: if only the value of the variable is used, a lvalue to rvalue conversion is applied; if the variable is used as an object, it is used as lvalue.
You can't use it in contexts where an lvalue is explicitly required, for example as argument to the address-of operator or mutating operators). Direct binding of lvalue references (without conversion) is such a context.
Some more examples (without detailed standardese analysis):
You can pass it to functions, unless the function parameter is a reference to which the variable can be directly bound.
For returning it from a function: if implicit conversion to the return type involves a user-defined conversion function, the rules for passing to a function apply. Otherwise you can return it, unless the function returns an lvalue (a reference) referring directly to the variable.
The key rule for odr-used variables, the "One Definition Rule" is in 3.2/3:
Every program shall contain exactly one definition of every non-inline
function or variable that is odr-used in that program; no diagnostic
required.
The "no diagnostic required" part means that programs violating this rule cause undefined behavior, which may range from failing to compile, compiling and failing in surprising ways to compiling and acting as if everything was OK. And your compiler need not warn you about the problem.
The reason, as others have already indicated, is that many of these violations would only be detected by a linker. But optimizations may have removed references to objects, so that no cause for linkage failure remains or else linking may sometimes occur only at runtime or be defined to pick an arbitrary instance from multiple definitions of a name.

Why won't this c++ lamba function compile?

Why does this fail to compile:
int myVar = 0;
myVar ? []()->void{} : []()->void{};
with following error msg:
Error 2 error C2446: ':' : no conversion from 'red_black_core::`anonymous-namespace'::< lambda1>' to red_black_core::anonymous-namespace::< lambda0>
While this complies correctly:
void left()
{}
void right()
{}
int myVar = 0;
myVar ? left() : right();
The return type of the ?: operator has to be deduced from it's two operands, and the rules for determining this type are quite complex. Lambdas don't satisfy them because they can't be converted to each other. So when the compiler tries to work out what the result of that ?: is, then there can't be a result, because those two lambdas aren't convertible to each other.
However, when you try to compute the functions, then you actually called them, but you didn't call the lambdas. So when you call the functions, they both have void, so the return type of ?: is void.
This
void left()
{}
void right()
{}
int myVar = 0;
myVar ? left() : right();
is equivalent to
int myVar = 0;
myVar ? [](){}() : [](){}();
Note the extra () on the end- I actually called the lambda.
What you had originally is equivalent to
compiler_deduced_type var;
if (myVar)
var = [](){};
else
var = [](){};
But- no type exists that can be both lambdas. The compiler is well within it's rights to make both lambdas different types.
EDIT:
I remembered something. In the latest Standard draft, lambdas with no captures can be implicitly converted into function pointers of the same signature. That is, in the above code, compiler_deduced_type could be void(*)(). However, I know for a fact that MSVC does not include this behaviour because that was not defined at the time that they implemented lambdas. This is likely why GCC allows it and MSVC does not- GCC's lambda support is substantially newer than MSVC's.
Rules for conditional operator in the draft n3225 says at one point
Otherwise, the result is a prvalue. If the second and third operands do not have the same type, and either
has (possibly cv-qualified) class type, overload resolution is used to determine the conversions (if any) to be
applied to the operands (13.3.1.2, 13.6). If the overload resolution fails, the program is ill-formed. Otherwise,
the conversions thus determined are applied, and the converted operands are used in place of the original
operands for the remainder of this section.
Up to that point, every other alternative (like, convert one to the other operand) failed, so we will now do what that paragraph says. The conversions we will apply are determined by overload resolution by transforming a ? b : c into operator?(a, b, c) (an imaginary function call to a so-named function). If you look what the candidates for the imaginary operator? are, you find (among others)
For every type T , where T is a pointer, pointer-to-member, or scoped enumeration type, there exist candidate operator functions of the form
T operator?(bool, T , T );
And this includes a candidate for which T is the type void(*)(). This is important, because lambda expressions yield an object of a class that can be converted to such a type. The spec says
The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator.
The lambda expressions can't be convert to any other of the parameter types listed, which means overload resolution succeeds, finds a single operator? and will convert both lambda expressions to function pointers. The remainder of the conditional opreator section will then proceed as usual, now having two branches for the conditional operator having the same type.
That's why also your first version is OK, and why GCC is right accepting it. However I don't really understand why you show the second version at all - as others explained, it's doing something different and it's not surprising that it works while the other doesn't (on your compiler). Next time, best try not to include useless code into the question.
Because every lambda is a unique type. It is basically syntactic sugar for a functor, and two separately implemented functors aren't the same type, even if they contain identical code.
The standard does specify that lambdas can be converted to function pointers if they don't capture anything, but that rule was added after MSVC's lambda support was implemented.
With that rule, however, two lambdas can be converted to the same type, and so I believe your code would be valid with a compliant compiler.
Both snippets compile just fine with GCC 4.5.2.
Maybe your compiler has no (or partial/broken) support to C++0x features such as lambda?
It doesn't fail to compile. It works just fine. You probably don't have C++0x enabled in your compiler.
Edit:
An error message has now been added to the original question! It seems that you do have C++0x support, but that it is not complete in your compiler. This is not surprising.
The code is still valid C++0x, but I recommend only using C++0x features when you really have to, until it's standardised and there is full support across a range of toolchains. You have a viable C++03 alternative that you gave in your answer, and I suggest using it for the time being.
Possible alternative explanation:
Also note that you probably didn't write what you actually meant to write. []()->void{} is a lambda. []()->void{}() executes the lambda and evaluates to its result. Depending what you're doing with this result, your problem could be that the result of calling your lambda is void, and you can't do much with void.