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.
Related
According to C++ ISO Draft (2020) 6.1 (Basics) :
A name is a use of an identifier (5.10), operator-function-id (12.6),
literal-operator-id (12.6.8), conversion-function-id (11.4.7.2), or
template-id (13.3) that denotes an entity or label (8.7.5, 8.2).
Every name that denotes an entity is introduced by a declaration.
Every name that denotes a label is introduced either by a goto
statement (8.7.5) or a labeled-statement (8.2).
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
A name can denote a entity, so it can denote an object and is introduced by a declaration in this case. A variable may be introduced by the declaration of an object, and in this case denotes the object. If I'm not misunderstading, the definitions of name and variable look very similar. What is the difference between a name and a variable?
(Particularly in the case that there is an intersection, e.g when they denote an object)
What is the difference between a name and a variable?
The most obvious (based upon your first quote) difference is that a name is more general than a variable. Every variable has a name, but not every name is of a variable. There are also names of functions, classes, operators, and templates. (This is not intended to be a complete list.)
Less obviously, a name is more specific than a variable, in the sense that a variable's name is only one aspect of the variable. I think your confusion comes from the fact that the name of a variable is necessarily introduced at the same time as the variable itself (your second and third quotes), and they go out of scope at the same time. There is no temporal separation of the two.
(Particularly in the case that there is an intersection, e.g when they denote an object)
I see this as somewhat philosophical. Let's take a similar situation: what is the difference between your name and yourself? Are you more than just a name? And yet, to identify you, others use your name.
It's not that different for variables. A variable has a name. That name is used to refer to the variable, often treated as being the variable. And yet, a variable is more than just a name; it also has a type and a value. The name does not intrinsically determine the type and value, yet out of convenience it is often used that way when talking about code. (That's not a bad thing, in the vast majority of cases.)
I would say that a variable has two things: a name and a value.
As far as names are concerned: variables can have names, but also functions, classes, ...
So a variable is an element, belonging to the C++ world (and lots of other programming languages).
A name is a property of much elements, such as variables, but also other ones.
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.
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.
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.
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).