Topic: Refering to, naming and denoting variables
Author: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Date: Fri, 30 Oct 2009 14:26:55 CST Raw View
Hello there. I find it difficult to get the difference of the above three
terms. Below are some examples where i show my problems, i would be glad if
you could comment on these. Thanks!
1) Variable
What exactly is it? The Standard just says
"A variable is introduced by the declaration of an object. The variable s
name denotes the object."
Does this mean a variable is an "entity'ed name"? I don't think so, because
the Standard uses "variable" as being equivalent to "named object".
2) Refering to a variable
This does mean we have an expression that in any way refers to an object,
and the object has a name:
int n;
int *np = &n;
n; *np; np[0]; (np+0)[0];
The three expressions above "refer to" a variable. "Denote" is the same
thing as "refer to". In this interpretation, an expression can never refer
to a reference, because evaluating such a reference will make the expression
refer to the referenced object instead.
3) Naming a variable
I think this means that one uses a name (either as the last component of a
qualified-id or as an unqualified-id) to refer to the object.
There are two interpretations i can think of:
3.1) The name when evaluated as an expression refers to the object:
int n;
int &nr = n;
nr; n;
Both name the variable "n".
3.2) The name before evaluation resolved to an object declaration by looking
up the id-expression:
int n;
int &nr = n;
nr; n;
Only the second expression "names" the variable n.
In this context, is it possible to "name" a reference? It seems tome only
3.2 allows this to happen, and under 3.1, any evaluation would first get rid
of the reference identity, and make the expression refer to the
object/function it references.
4) The C++0x draft currently says in 5.19/2:
"A conditional-expression is a constant expression unless it involves one of
the following ...:
- an lvalue-to-rvalue conversion (4.1) unless it is applied to
* an lvalue of effective integral type that refers to a non-volatile
const variable or static data member initialized with constant expressions"
Consider this one:
int const A = 10;
void f(int const* AR) { int a[*AR]; }
int main() { f(&A); }
This would seem to be valid to me, since "*AR" seems to "refer to" a non-
volatile const variable.
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Alf P. Steinbach" <alfps@start.no>
Date: Fri, 30 Oct 2009 19:21:41 CST Raw View
* Johannes Schaub (litb):
> Hello there. I find it difficult to get the difference of the above three
> terms. Below are some examples where i show my problems, i would be glad if
> you could comment on these. Thanks!
>
> 1) Variable
>
> What exactly is it? The Standard just says
>
> "A variable is introduced by the declaration of an object. The variable s
> name denotes the object."
>
> Does this mean a variable is an "entity'ed name"? I don't think so, because
> the Standard uses "variable" as being equivalent to "named object".
Yes, a variable in the C++ standard's sense is a named object /introduced by an
object declaration/. And an object, in the C++ standard's sense, is just a
region of memory, with an associated type. The sizeof operator gives you the
size in bytes of the region of memory.
Complication, but just disregard this if it sounds too complicated :-): in the
C++ standard's sense a "region" is not necessarily contiguous!
However, except possibly for Microsoft's C++/CLI, which is a non-standard
extension of C++ (and I think not even there), any /variable/, that is any named
object introduced by an object declaration, is in practice a contiguous region
of memory. There's some dissent over whether that was meant to be a formal
requirement. As I recall Dave Abrahams once argued strongly that the original
intent was to not introduce such a requirement, that great effort was expended
to not introduce such a requirement, but in practice it's there.
Objects spread over two or more separate regions of memory occur in the context
of virtual multiple inheritance, where a single base class object O is logically
present in two or more derived class objects, say A and B. Then it's physically
impossible for O to be physically inside both A and B. Hence A, or B, or both,
must logically contain an O sub-object that is physically outside. The only way
to name such an object (where the sizeof operator doesn't report the actual
size) is to bind it to a reference. And thus, logically, naming an object by
binding it to a reference can not formally constitute a variable, so this is a
Very Fine Distinction on the concept of variable in C++: a reference declaration
is not an object declaration, and so the thing declared is not a variable even
though it is a name, and even though that name refers to an object.
> 2) Refering to a variable
>
> This does mean we have an expression that in any way refers to an object,
> and the object has a name:
>
> int n;
> int *np = &n;
>
> n; *np; np[0]; (np+0)[0];
>
> The three expressions above "refer to" a variable. "Denote" is the same
> thing as "refer to".
Well that's a matter of terminology.
The critical issue is whether the variable is introduced via an object
declaration.
> In this interpretation, an expression can never refer
> to a reference, because evaluating such a reference will make the expression
> refer to the referenced object instead.
>
> 3) Naming a variable
>
> I think this means that one uses a name (either as the last component of a
> qualified-id or as an unqualified-id) to refer to the object.
>
> There are two interpretations i can think of:
>
> 3.1) The name when evaluated as an expression refers to the object:
>
> int n;
> int &nr = n;
>
> nr; n;
>
> Both name the variable "n".
The first declaration is an object declaration and so n is a variable.
The second is not an object declaration and so rn is not a variable.
There is no standard C++ way that a program can detect this difference,
though. ;-)
> 3.2) The name before evaluation resolved to an object declaration by looking
> up the id-expression:
>
> int n;
> int &nr = n;
>
> nr; n;
>
> Only the second expression "names" the variable n.
No, both name it.
> In this context, is it possible to "name" a reference? It seems tome only
> 3.2 allows this to happen, and under 3.1, any evaluation would first get rid
> of the reference identity, and make the expression refer to the
> object/function it references.
You can't name the reference itself because it's not an object, but you can
introduce additional names for the referred to object.
> 4) The C++0x draft currently says in 5.19/2:
>
> "A conditional-expression is a constant expression unless it involves one of
> the following ...:
>
> - an lvalue-to-rvalue conversion (4.1) unless it is applied to
> * an lvalue of effective integral type that refers to a non-volatile
> const variable or static data member initialized with constant expressions"
>
> Consider this one:
>
> int const A = 10;
> void f(int const* AR) { int a[*AR]; }
> int main() { f(&A); }
>
> This would seem to be valid to me, since "*AR" seems to "refer to" a non-
> volatile const variable.
I think you have a point here. Some additional qualification would be needed for
the wording above to be Perfect(TM). However, I think anyone reading the
standard is sufficiently aware of how the language works to not be confused by
the possibility that a function argument might be regarded as a variable, or
that const in the context above refers to originally const.
Cheers,
- Alf
PS: I didn't discover until the end that this is [comp.std.c++]. I thought it
was [comp.lang.c++]. Otherwise I'd have added references to the standard, and
I'd not assumed, as I did, that this was a newbie's confusion over "what is a
variable". But too late to fix now without several minutes' work! Hope OK? :-)
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Date: Sat, 31 Oct 2009 00:57:38 CST Raw View
Alf P. Steinbach wrote:
> * Johannes Schaub (litb):
>> Hello there. I find it difficult to get the difference of the above three
>> terms. Below are some examples where i show my problems, i would be glad
>> if you could comment on these. Thanks!
>>
>> 1) Variable
>>
>> What exactly is it? The Standard just says
>>
>> "A variable is introduced by the declaration of an object. The variable s
>> name denotes the object."
>>
>> Does this mean a variable is an "entity'ed name"? I don't think so,
>> because the Standard uses "variable" as being equivalent to "named
>> object".
>
> Yes, a variable in the C++ standard's sense is a named object /introduced
> by an object declaration/. And an object, in the C++ standard's sense, is
> just a region of memory, with an associated type. The sizeof operator
> gives you the size in bytes of the region of memory.
>
> Complication, but just disregard this if it sounds too complicated :-): in
> the C++ standard's sense a "region" is not necessarily contiguous!
>
> However, except possibly for Microsoft's C++/CLI, which is a non-standard
> extension of C++ (and I think not even there), any /variable/, that is any
> named object introduced by an object declaration, is in practice a
> contiguous region of memory. There's some dissent over whether that was
> meant to be a formal requirement. As I recall Dave Abrahams once argued
> strongly that the original intent was to not introduce such a requirement,
> that great effort was expended to not introduce such a requirement, but in
> practice it's there.
>
> Objects spread over two or more separate regions of memory occur in the
> context of virtual multiple inheritance, where a single base class object
> O is logically present in two or more derived class objects, say A and B.
> Then it's physically impossible for O to be physically inside both A and
> B. Hence A, or B, or both, must logically contain an O sub-object that is
> physically outside. The only way to name such an object (where the sizeof
> operator doesn't report the actual size) is to bind it to a reference. And
> thus, logically, naming an object by binding it to a reference can not
> formally constitute a variable, so this is a Very Fine Distinction on the
> concept of variable in C++: a reference declaration is not an object
> declaration, and so the thing declared is not a variable even though it is
> a name, and even though that name refers to an object.
>
Ah, thanks for the detailed explanations - i didn't know there is actually a
use for this "non-continuous" thing before. So just to make sure i get it:
The only way to refer to name such an object is by a reference, because when
creating such an object right away, you can only do that as a complete
object, and then it's not a virtual base anymore (of course).
But why does this preclude references as variables? I've seen the Standard
uses "variable" currently as including both named objects and references,
and there is a defect report about fixing this, essentially making
"variable" include references, but the committee seem to be waiting on this.
Can you please detail on the reason - has this got something to do with
these things? E.g in the following, why can't b or c be a variable:
struct A { int b; };
struct B : virtual A { };
struct C : virtual A { };
struct D : B, C { };
D d;
B &b = d;
C &c = d;
Now, if i understood you right, either the object referred by b, or the
object referred by c or both are not continuous, because there is only one A
sub-object. But why does this forbid making b or c a variable? Couldn't one
simply enhance the definition of "variable" to say:
"A variable is introduced by the declaration of an object or reference. The
variable's name denotes the object or reference."
>
>> In this interpretation, an expression can never refer
>> to a reference, because evaluating such a reference will make the
>> expression refer to the referenced object instead.
>
>
>
>>
>> 3) Naming a variable
>>
>> I think this means that one uses a name (either as the last component of
>> a qualified-id or as an unqualified-id) to refer to the object.
>>
>> There are two interpretations i can think of:
>>
>> 3.1) The name when evaluated as an expression refers to the object:
>>
>> int n;
>> int &nr = n;
>>
>> nr; n;
>>
>> Both name the variable "n".
>
> The first declaration is an object declaration and so n is a variable.
>
> The second is not an object declaration and so rn is not a variable.
>
> There is no standard C++ way that a program can detect this difference,
> though. ;-)
>
Well, i did some experiments before, and it turned out the following fails
at least on comeau and GCC:
int a;
int &ra = a;
template<int &I> struct foo { };
foo<ra> f;
The Standard says that the argument shall be an id-expression being the
address of an object of function. It says also that it "refers" to those
objects or functions at 14.3.2/1. It's ambiguous to me whether this means
looking-up to an object declaration, or whether it means actually evaluating
to the object identity (which would make the above code valid, to me).
>> 4) The C++0x draft currently says in 5.19/2:
>>
>> "A conditional-expression is a constant expression unless it involves one
>> of the following ...:
>>
>> - an lvalue-to-rvalue conversion (4.1) unless it is applied to
>> * an lvalue of effective integral type that refers to a non-volatile
>> const variable or static data member initialized with constant
>> expressions"
>>
>> Consider this one:
>>
>> int const A = 10;
>> void f(int const* AR) { int a[*AR]; }
>> int main() { f(&A); }
>>
>> This would seem to be valid to me, since "*AR" seems to "refer to" a non-
>> volatile const variable.
>
> I think you have a point here. Some additional qualification would be
> needed for the wording above to be Perfect(TM). However, I think anyone
> reading the standard is sufficiently aware of how the language works to
> not be confused by the possibility that a function argument might be
> regarded as a variable, or that const in the context above refers to
> originally const.
>
I'm silly in that i overlooked that "*AR" is already an lvalue-to-rvalue
conversion of a local variable. My initial "test-case" was using this code:
int const A = 10;
void f(int const& AR) { int a[AR]; }
int main() { f(A); }
Which indeed doesn't have that problem. But then i discovered that it says
"an id-expression that refers to a variable or data member of reference
type;", and i quickly changed into a pointer, without thinking about it :)
Anyway, i think the intend of it is to forbid any references, but it's
actually non-sensical to me, because an expression can never refer to a
reference. For this reason, wouldn't it be better to define a concept called
"naming" like the following:
"In this International Standard, 'naming an entity' refers to the use of a
name that is resolved to a declaration of that entity. [Note: Thus, it is
possible for an id-expression to name a reference, but it's impossible for
such an expression to refer to a reference]".
And use it in these paragraphs (template argument constraints, constant
expression constraints, etc...)?
> Cheers,
>
> - Alf
>
> PS: I didn't discover until the end that this is [comp.std.c++]. I thought
> it was [comp.lang.c++]. Otherwise I'd have added references to the
> standard, and I'd not assumed, as I did, that this was a newbie's
> confusion over "what is a variable". But too late to fix now without
> several minutes' work! Hope OK? :-)
>
Yep, no worries :)
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]