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.
Related
I am trying to overhaul some code to use modules instead of common blocks for globally-scoped variables.
During my refactor, I've been noticing lots of sections like this:
SUBROUTINE WEIRDSUB()
INCLUDE 'parameters'
COMPLEX BDY1, BDY2
COMMON/FBDY/ BDY1(NY,NZ,NX), BDY2(NY,NZ,NX)
...
! NOTE: there is nothing here that assigns any values to BDY1
...
CALL NORM(BDY1) ! runs no problem?
...
How is a having a locally-defined variable with the same name as a common block variable ok? Is the COMPLEX BDY1 declaration somehow imparting a type on the memory of the common block?
complex bdy1
does not directly declare a local variable bdy1. It simply declares the type of some entity with name bdy1 to be complex.
This is true for other type declaration statements.
In this case the entity bdy1 is also declared to be in the common block, and an array with the given extents. There is no conflict.
Entities in common block may also be implicitly typed, or have a type declaration following the common statement (if it agrees with implicit typing rules).
Other examples of a type declaration statement not declaring local variables would be functions, dummy arguments, constants.
(See comments as the example changed a lot.)
First, I'll note that the example you provide is not correct syntax. The fourth line should read:
COMMON /A/ A(NX,NY)
In most cases, a local name and a global name (the COMMON name is global) can't both be used in contexts where both are visible. There are exceptions, though. Quoting from the standard:
"Within its scope, a local identifier of an entity of class (1) or class (4) shall not be the same as a global identifier used in that scope unless the global identifier
is used only as the use-name of a rename in a USE statement,
is a common block name (19.3.2),
is an external procedure name that is also a generic name, or
is an external function name and the inclusive scope is its
defining subprogram (19.3.3)"
The variable name is a class(1) entity (this is most local names) and the common block class(4). You can see that the common block name is an allowed exception. This works because you can't reference the common block name without the /A/ syntax, so it is not ambiguous.
[basic.lookup]/1:
The name lookup rules apply uniformly to all names (including typedef-names (10.1.3), namespace-names
(10.3), and class-names (12.1)) wherever the grammar allows such names in the context discussed by a
particular rule. Name lookup associates the use of a name with a set of declarations (6.1) of that name. The
declarations found by name lookup shall either all declare the same entity or shall all declare functions; in the
latter case, the declarations are said to form a set of overloaded functions (16.1). Overload resolution (16.3)
takes place after name lookup has succeeded. The access rules (Clause 14) are considered only once name
lookup and function overload resolution (if applicable) have succeeded. Only after name lookup, function
overload resolution (if applicable) and access checking have succeeded are the attributes introduced by the
name’s declaration used further in expression processing (Clause 8).
What are those attributes introduced by the names´s declaration?
This sentence is visible in the N1638 - C++ Working Draft from April 2004, so it doesn't refer specifically to attributes of the form [[...]], which were introduced to the standard by N2761 - Towards support for attributes in C++
(Revision 6) in 2008.
[basic.lookup]/1
Only after name lookup, function overload resolution (if applicable) and access checking have succeeded are the attributes introduced by the name’s declaration used further in expression processing (clause 5).
Also [basic.def]/1
A declaration (clause 7) introduces names into a translation unit or redeclares names introduced by previous declarations. A declaration specifies the interpretation and attributes of these names.
From the above, and looking at the five other occurrences of 'attribute' in that paper, it appears to me that 'attribute' just means "information about the name". So in this case, things like extern, friend, the body of a function definition, and anything else you can say about a name in a declaration, that wasn't part of determining the interpretation of a name.
Since C++11 this would also include "generalised attributes" in the form [[..]]. There's a hint here, N2761 didn't introduce 'attributes', it just gave us a generalised syntax for them.
Function parameters, conversely, would not be 'attributes' in this sense, as the interpretation of the function name involves the parameters as part of overload resolution. The return type would be an attribute, since we don't look at it until we know what the name means, and which overload we've chosen.
In a slightly-more-standardese sense, I think you can say that the 'specifiers' are attributes, while the 'declarators' specify the interpretation of a name.
Pratically, I would say (without checking for a more-specific rule) that this is the rule that requires that deleted functions survive all the way through the lookup and name resolution process, and then fail the compilation.
Otherwise, a crafty compiler author might want to save their users some grief by eliminating deleted functions earlier, on the grounds that you can't call a deleted function, so why bother including it in the overload set?
In C++, is there a difference between name binding and name lookup in? The working draft C++14 standard (N4296) defines name lookup in (3.4) as
Name lookup associates the use of a name with a declaration (3.1) of that name.
I can't find a definition for name binding in the standard, but the IBM Knowledge Center documentation for their XL C/C++ compiler defines:
Name binding is the process of finding the declaration for each name that is explicitly or implicitly used in a template.
The only distinctions between the two definitions seem to be that (1) name binding refers specifically to a name used in a template and (2) name binding refers to a name, while name lookup refers to the use of a name.
However, Section (13.3) on Overload Resolution in the C++ standard mentions binding frequently, but without defining it. The way 'binding' is used in this context makes it seem that binding refers to the association of an argument with a function parameter.
At first, this definition seems different from either of the other two definitions, thought it fits (broadly) the definition of name lookup if we assume that the name of the function is being bound to its declaration by comparing the types of arguments and parameters. That isn't exactly the sense used in Section (13.3), but I'm trying to make sense of the standard without a proper definition.
In short, if anyone has a good definition of 'name binding' or 'binding', I'd be grateful.
Having read the relevant parts of Wilson & Clark Comparative Programming Languages, I think I have a better understanding of the topic. If I surmise correctly, the term 'binding' covers a gamut of related terms, including name-declaration binding, name–type binding, declaration-reference binding, reference-value binding, and name-value binding.
"Name lookup" seems to be a synonym for name-declaration binding. The other uses of 'binding' in the C++14 standard relate to various combinations of the other varieties of binding.
Please correct me if I'm wrong!
Up until now I was under the impression that things like immutable and const were storage classes. In a recent video (at around 11:55) Walter Bright states that immutable is not a storage class, but rather it's a type constructor. In the official documentation, immutable, const, and among many other keywords, are listed as being storage classes:
StorageClass:
abstract
auto
const
deprecated
enum
extern
final
immutable
inout
shared
nothrow
override
pure
__gshared
Property
scope
static
synchronized
Is this list wrong? Some of it doesn't make sense(e.g., deprecated, override).
I know static and ref are storage classes, but what's the rest? And which one of the keywords in D are type constructors?
I would point out that there is a big difference between a grammar rule named StorageClass, and what is semantically a storage class in the language. The grammar rules have to do with parsing, not the semantic phase of compilation.
First off, TDPL, chapter 8, is explicitly about type qualifiers (for which Walter used the term type constructor). There are only 3 of them in D:
const
immutable
shared
All three of them are a part of the type that they modify. Such is not true with storage classes such as ref.
inout is what TDPL calls a "wildcard qualifier symbol," so it's a placeholder for a type qualifier rather than really being either a type qualifer or a storage class.
Now, as to what's a storage classes or not, I give two quotes from TDPL:
Each function parameter (base and exponent in the example above) has, in addition to its type, an optional storage class that decides the way that arguments are passed to the function when invoked.
(from pages 6 - 7)
Although static is not related to passing arguments to functions, discussing it here is appropriate because, just like ref, static applied to data is a storage class, meaning an indication about a detail regarding how data is stored.
(from page 137)
Also, there's this line with regards to storage classes in C which seems to be used quite a bit in explanations on storage classes in C found online:
A storage class defines the scope (visibility) and life time of variables and/or functions within a C Program.
A storage class has no effect on the type of a variable, just how it's stored. Unfortunately, I can't find an exact list of storage classes in D, and people are quite liberal with the term storage class, using it even when it doesn't apply. Pretty much any attribute applied to a type save for access modifiers seems to get called a storage class, depending on who's talking. However, there are a few which are beyond a doubt storage classes:
enum (when used as a manifest constant)
extern
lazy
out
ref
scope
static
lazy, out, and ref can be used to modify function parameters and indicate how they're passed, whereas enum and static are used to indicate how the variables are stored (which is nowhere in the case of enum, since manifest constants are copy-pasted everywhere that they're used rather than being actual variables). extern affects linkage.
in is a hybrid, since it's a synonym for scope const, and while scope is a storage class, const is a type qualifier.
The online documentation also refers to auto and synchronized as storage classes, though I don't know on what basis. auto is like inout in that it's a placeholder (in its case a placeholder for a type rather than a type qualifier) and therefore indicates nothing about how a type is stored, so I wouldn't have thought that it would be a storage class. synchronized doesn't modify variables but rather classes.
__gshared is probably a storage class as well, though it's a bit funny, since it does more or less what shared (which is a type qualifier) does, but it's not part of the type.
Beyond that, I don't know. The fact that synchronized is listed as a storage class implies that some of the others (such as final) might be, but (like synchronized) they have nothing to do with how variables are stored or linked. So, I don't know how they could be considered storage classes.
I'll ask on the newsgroup though and see if I can get a more definitive list.
EDIT: It seems that there is no definitive, official list of storage classes in D. The term is used for almost any attribute used on a variable declaration which doesn't affect its type (i.e. not a type qualifier). It seems that Walter and Andrei tend to make a big point about the type qualifiers to underline which attributes actually affect the type of a variable, but the term storage class hasn't been given anywhere near the same level of importance and ends up being used informally rather than per any rigorous definition.
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.