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.
Related
I have come across different macros which enable deprecation of member attributes and functions but none of them discuss the possibility of deprecating static class members.
I read that even in C++14 deprecation of static members is not allowed.
Is there any specific reason for this?
Let's get some facts:
The wording for the [[deprecated]] attribute is the following
(based on N4269 7.6.5 [dcl.attr.deprecated], emphasis mine):
The attribute may be applied to the declaration of a class, a typedef-name, a variable, a non-static data
member, a function, a namespace, an enumeration, an enumerator, or a template specialization.
The misleading part is the explicit appearance of "non-static data members" without its counterpart at the same level in this list, but in that same list there are two other elements of interest.
The description of a variable is (based on 3 [basic]) :
A variable is introduced by the declaration of a reference other than a non-static data member or of an
object. The variable’s name, if any, denotes the reference or object.
Which means that saying a variable includes static data members
A static member function is a function (a red car is a car, this is a logical conclusion and i don't seem to find anything counter indicating this in the standard).
There isn't any syntax or behaviour problem applying particularly to static members, a static function is pretty much a free function in a namespace and static data member is more or less a global variable in a namespace and you can deprecate free functions and global variables..
As a bonus, it actually works in major compilers.
Summing up all this facts basically means that the [[deprecated]] attribute may actually be applied to a static data member, a non-static data member and a static member function, among other things.
So to answer your question, from my understanding, deprecating static members is actually allowed by the standard.
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.
In C++ 5.1.1/3 [expr.prim.general] it says:
The type and value category [of this] are defined within a static member function.
What does this mean? How is it relevant?
Note that:
this shall not appear in the declaration of a static member function
The language in the standard can be traced to n3282, which is a resolution for defects 1207 and 1017. In particular, the language appears in the proposed resolution for defect 1207, and thus should be considered in the context of the standard as it stood at the time that defect was addressed. At that time there was some concern over the rewriting of id-expressions into member access expressions using *this (9.3.1p3), in particular in the context of trailing-return-type declarations (see issue 945).
If we compare the proposed resolution to defect 1207 to the eventual language in n3282 and subsequently in the standard, there is one significant difference to 9.3.1p3:
Defect 1207:
When an id-expression (5.1 [expr.prim]) that is not part of a class member access syntax (5.2.5 [expr.ref]) and not used to form a pointer to member (5.3.1 [expr.unary.op]) is used in the declaration of a member function of class X, if name lookup (3.4 [basic.lookup]) resolves the name...
n3282 and C++11:
When an id-expression (5.1 [expr.prim]) that is not part of a class member access syntax (5.2.5 [expr.ref]) and not used to form a pointer to member (5.3.1 [expr.unary.op]) is used in a member of class X in a context where this can be used (5.1.1 [expr.prim.general]), if name lookup (3.4 [basic.lookup]) resolves the name [...]
It is apparent that the proposed resolution to defect 1207 carried the belief that id-expressions (to a static member) within a static member functions would need to be transformed to *this member access expressions and thus would need access to the type and value category of this. By the time n3282 was written this had been resolved in favour of the qualified-id transformation (also 9.3.1p3) which does not require this, but the language in 5.1.1p3 remained vestigially.
I would recommend raising this issue on the C++ standards discussion newsgroup; it may be possible to get the vestigial language removed editorially.
n3035 says: (2010-02-16)
A variable is introduced by the declaration of an object. The variable's
name denotes the object.
n3090 says: (2010-03-29)
A variable is introduced by the declaration of a reference other than a
non-static data member or of an object. The variable's name denotes the
reference or object.
n3242 says: (2011-02-28)
A variable is introduced by the declaration of a reference other than a
non-static data member or of an object. The variable's name denotes the
reference or object.
CAN any one explain the difference interms (or) with the help of an program(exactly what it say's)
this is the statement from ISO standard C++
I seen this link :
Why was the definition of a variable changed during the development of C++11?
but this is not(full meaning) my question ...
Consider:
int x = 42;
int& rx = x;
x is a variable; should rx also be considered a variable? Many of the Standard's requirements about non-reference variables also apply to references. It's obviously a pain to have to stipulate "variables or references to variables" constantly throughout the Standard, so if the definition of a variable can include references - perhaps with the occasional "except for references", then the Standard may be - on balance - simplified. It looks to me like the revisions were exploring this balance.
This was a CWG defect #633 in ISO C++03
Also check out n2993 that deals with core issue# 633 i.e
"Specifications for variables that should also apply to references"
The goal of these changes is to expand the meaning of "variable" to encompass both named objects and references, and to apply the term consistently wherever feasible.
Consider the following snippet:
struct Foo
{
static const T value = 123; //Where T is some POD-type
};
const T Foo::value; //Is this required?
In this case, does the standard require us to explicitly declare value in a translation unit? It seems I have conflicting information; boost and things like numeric_limits from the STL seem to do this sort of thing just like in my snippet.
OTOH, I remember reading somewhere (albeit a long long time ago) that you're still required to provide a declaration in a translation unit.
If this is the case, what about template specialization? Will each specialization require a declaration?
I'd appreciate your comments as to what the "right way" is.
You have to provide a definition in a translation unit too, in case you use the value variable. That means, if for example you read its value.
The important thing is that the compiler is not required to give a warning or error if you violate that rule. The Standard says "no diagnostic required" for a violation.
In the next C++ Standard version, the rule changed. A variable is not used when it is used as a constant expression. Simply reading value above where the variable is initialized directly in the class means that still no definition is required then.
See the definition of use in section 3.2 One Definition Rule of the Standard and requirement for a definition for static data-members in 9.4.2, paragraph 4 and 5 (in the C++98 Standard. Appears in paragraph 3 and 4 in the n2800 draft of the next Standard).
Correction: The rule already changed for c++03: If the variable appears where a integral constant expression is required, no definition is needed (quoting from an unofficial revisions list for the 2003 update), see resolution for this language defect report:
An expression is potentially evaluated unless it appears where an integral constant expression is required (see 5.19), is the operand of the sizeof operator (5.3.3), or is the operand of the typeid operator and the expression does not designate an lvalue of polymorphic class type (5.2.8)...
Note that even then, many uses are in cases where an integral constant is not required. Cases where one is, is in array dimensions or in template metaprogramming. So strictly speaking (see this report), only the c++1x solution provides really guarantee that in obvious cases also like "s == string::npos" where an integral constant is not required the definition of the static member is not needed, because the next Standard has a different, better wording of 3.2. This is however quite theoretical stuff, since most (all?) compiler don't moan anyway. Thanks for the guy in the comment section for telling me.
To add on to what litb said, from my copy of n2798:
9.4.2
[...]
2 The declaration of a static data member in its class definition is not a definition and
may be of an incomplete type other than cv-qualified void. The definition for a static
data member shall appear in a namespace scope enclosing the member’s class definition. In
the definition at namespace scope, the name of the static data member shall be qualified
by its class name using the :: operator.
You don't have to provide a definition for static integral constant members if you don't use them in some way that requires them to be stored in memory somewhere (e.g. take the address of such a member). See Stroustrup's The C++ Programming Language, section 10.4.6.2.
Edit:
Oops, I just re-read the question, and the question was for some type T. In general you would need to provide a definition, I agree. But if you used something from the int family, you wouldn't necessarily have to (with the caveat above).