Topic: What is an r-value?? Please, forgive me!! :(
Author: Hyman Rosen <hyrosen@mail.com>
Date: Thu, 20 Jun 2002 17:28:56 GMT Raw View
Gabriel Dos Reis wrote:
> Does that mean that what is offered is a crystal clear explanation,
> even when those who offered their explanations said they weren't sure?
We're sure now, after having found the relevant portions of
the standard, 5.2.2/4 and 8.5.3/5.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: jpotter@falcon.lhup.edu (John Potter)
Date: Thu, 20 Jun 2002 17:29:06 GMT Raw View
On Mon, 17 Jun 2002 18:00:17 GMT, Gabriel Dos Reis
<gdr@merlin.nerim.net> wrote:
>jpotter@falcon.lhup.edu (John Potter) writes:
>| It is clearly not specified as unspecified behavior either.
>The standard doesn't have to say explicitly that a behaviour is
>undefined for that to be. It suffices that it omits a descripion of
>an explicit behaviour.
Yes, thank you for giving the reference in another article.
Please read above. I said unspecified (1.3.13) not undefined.
>Nobody body is disputing that there is an observable behaviour. My
>question is whether that observable behaviour is the one required by
>the standard.
Sorry, I have not seen a question. I see only a repeated statement
that the standard does not state the behavior and it is thus
undefined.
What do you find ambiguous about
| a temporary is created and initialized from the initializer expression
| ... the reference is then bound to the temporary
void f (int const& a, int const& b);
f(42, 42);
Facts: There are two references to be initialized. There are two
corresponding initializer expressions.
What's the problem? Please reword to fix it. Is it different from
int const& a(42);
int const& b(42);
If so, how? Yes, there is a sequence point. If you think it makes
a difference, explain why.
If you are still on the possibility of doing them in parallel, I
accept that they may be done in parallel. How does creating two
temporaries in parallel allow them to become one?
If you are discussing the intent, not the words, of the standard, my
appologies for misunderstanding.
John
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.de (James Kanze)
Date: 19 Jun 2002 15:10:07 GMT Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote in message
news:<bvMDfdBcEbD9Ewll@robinton.demon.co.uk>...
> In article <86d6urzgsn.fsf@alex.gabi-soft.de>, James Kanze
> <kanze@alex.gabi-soft.de> writes
> >(For reference, the orginal program was:
> > #include <iostream>
> > #include <ostream>
> > void
> > f( int const& a, int const& b )
> > {
> > std::cout << (&a == &b ? "true" : "false") << '\n' ;
> > }
> > int
> > main()
> > {
> > f( 5, 5 ) ;
> > return 0 ;
> > }
> >And the proposition is that on a conforming implementation, this
> >program *must* output "false".)
> However, if you avoid taking the address I think that only one is
> required :-) I.e. you only get two when you look.
And if you don't do anything with the values, none are required:-).
For any given program, barring undefined behavior, the standard
specifies a set of observable behavior. The compiler can do anything
it wants in order to get that observable behavior.
--
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)69 63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.de (James Kanze)
Date: Wed, 19 Jun 2002 10:10:12 CST Raw View
Gabriel Dos Reis <gdr@codesourcery.com> wrote in message
news:<m3bsaagxpo.fsf@merlin.nerim.net>...
> James Kanze <kanze@alex.gabi-soft.de> writes:
> [...]
> | In the section Gennaro quotes, the words "is created" are very
> | clear: when binding an rvalue to a const reference, an "object" is
> | created. If there are two references, two objects must be
> | created.
> | Of course, if you read the entire paragraph, it offers an
> | implementation defined choice, and an implementation may bind "the
> | object represented by the rvalue [...]". The reference to 3.10,
> | here, suggests that this option is only relevant to class types --
> | rvalues of basic types do not have "objects". But it is far from
> | clear.
> If I keep asking for a crystal clear clarification, it is precisely
> because I don't find the rules that clear.
IMHO, there are two separate issues: what the standard says, and what
the intent was. With regards to the intent, of course, we can only
just guess -- I wasn't present at the meeting where this paragraph was
discussed, and I don't think you were either. (As I said earlier, I
have a sneaking suspicion that this precise issue wasn't discussed.)
With regards to what is said, I have offered an interpretation, based
on the concrete wording in the standard. Others seem to accept that
interpretation. You have said that you don't agree, but you have not
offered an alternative interpretation of these particular words.
> I'm looking for something other than "Do you have anything to offer
> other than your insistence?", because that answer doesn't offer any
> clarification.
They are asking for your interpretation. What do you think that this
passage means (or could mean -- it is sufficient that another
interpretation is possible).
> [...]
> | |> The two references are bounded to a created temporary.
> | Unless you argue that 5 in my original example is an object
> I'm certainly not arguing that.
> | (and that the implementation chooses to bind to a specific
> | object), I think you are forced to admit one creation per
> | reference. Whatever that means.
> | A priori, I would interpret the standard to say that the two
> | addresses in my example must be different. But I rather suspect
> | that the fact that the standard says this is more accidental than
> | anything else, and I certainly wouldn't mind a clarification. One
> | way or the other.
> I would certainly welcome a clarification. Not a "Do you have
> anything to offer other than your insistence?"
Well, one obvious clarification would be that the standard means what
it says, and that what it says *is* intentional.
--
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)69 63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Hyman Rosen <hyrosen@mail.com>
Date: Thu, 20 Jun 2002 17:27:08 GMT Raw View
Gabriel Dos Reis wrote:
> Actually, that paragraph says a temporary is created and a
> reference is bound to that temporary. But that paragraph fails to say
> unambigously that two distinct references should be bound to distinct
> temporaries -- hence forbidding value sharing. My position is that in the
> absence of explicit descrption, an undefined behaviour should be expected.
5.2.2/4 says
When a function is called, each parameter (8.3.5) shall be
initialized (8.5, 12.8, 12.1) with its corresponding argument.
For the case in question, the final clause of 8.5.3/5 says how to do this.
I don't see how it could be any more clear.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Hyman Rosen <hyrosen@mail.com>
Date: Thu, 20 Jun 2002 17:28:48 GMT Raw View
Gabriel Dos Reis wrote:
> 1.3.12 says:
> Undefined behavior may also be expected when this International
> Standard omits the description of any explicit definition of
> behavior.
Which does not apply in this case, since the standard provides
an explicit definition of behavior.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@merlin.nerim.net>
Date: Sat, 15 Jun 2002 16:25:28 GMT Raw View
Gennaro Prota <gennaro_prota@yahoo.com> writes:
[...]
| > Since there are two separate bindings, with two separate
| >temporary values, it would seem that we have two separate objects.
|
| The section you refer to is 8.5.3/5 (emphasis mine): "a temporary of
| type "cv1 T1" _is created_ and initialized from the initializer
| expression using the rules for a non-reference copy initialization
| (8.5). The reference is then bound to the temporary."
|
| The words "is created" seem not to leave enough space for the compiler
| to reuse an already created object when doing the second binding. Of
| course I'm assuming that the two bindings cannot happen
| simultaneously. Any other opinions? :)
Yes, I have one because I think you're reading too much into the standard.
The order in which the temporaries are created is not specified
by the standard and there is no way for a conforming program to
know that for fundamental types.
The two references are bounded to a created temporary.
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gennaro Prota <gennaro_prota@yahoo.com>
Date: Sat, 15 Jun 2002 17:06:31 GMT Raw View
On Sat, 15 Jun 2002 16:25:28 GMT, Gabriel Dos Reis
<gdr@merlin.nerim.net> wrote:
>Gennaro Prota <gennaro_prota@yahoo.com> writes:
>
>[...]
>
>| > Since there are two separate bindings, with two separate
>| >temporary values, it would seem that we have two separate objects.
>|
>| The section you refer to is 8.5.3/5 (emphasis mine): "a temporary of
>| type "cv1 T1" _is created_ and initialized from the initializer
>| expression using the rules for a non-reference copy initialization
>| (8.5). The reference is then bound to the temporary."
>|
>| The words "is created" seem not to leave enough space for the compiler
>| to reuse an already created object when doing the second binding. Of
>| course I'm assuming that the two bindings cannot happen
>| simultaneously. Any other opinions? :)
>
>Yes, I have one because I think you're reading too much into the standard.
>
>The order in which the temporaries are created is not specified
>by the standard and there is no way for a conforming program to
>know that for fundamental types.
But I'm not thinking of a particular "order". I'm thinking of the fact
that the binding is a run-time operation, right?; and you cannot do
the two bindings simultaneously, right?. Thus, when you do the second
binding (whichever it is, first parameter's or second one's) you have
to _create_ a temporary. If you bind the reference to an existing
temporary you are not creating, you are simply "reusing" the
temporary.
I'm not sure that this was the intent and I'm open to other ideas but
I don't see in the wording the necessary freedom to allow your
interpretation.
Genny.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: jpotter@falcon.lhup.edu (John Potter)
Date: Sat, 15 Jun 2002 17:53:27 GMT Raw View
On Sat, 15 Jun 2002 16:25:28 GMT, Gabriel Dos Reis
<gdr@merlin.nerim.net> wrote:
> Gennaro Prota <gennaro_prota@yahoo.com> writes:
> The order in which the temporaries are created is not specified
> by the standard and there is no way for a conforming program to
> know that for fundamental types.
Order has nothing to do with it.
The standard says that when a builtin rvalue is used, a temporary is
created to bind to the const reference. The conforming program from
James has observable behavior which will detect whether two or one
temporaries were created.
> The two references are bounded to a created temporary.
Each reference is bound to a created temporary. The standard says
that a temporary shall be created. Where do you find anything which
says that an implementation might not bother if it can reuse some
other temporary which happens to have the same lifetime?
John
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@merlin.nerim.net>
Date: Sat, 15 Jun 2002 23:16:21 GMT Raw View
jpotter@falcon.lhup.edu (John Potter) writes:
| On Sat, 15 Jun 2002 16:25:28 GMT, Gabriel Dos Reis
| <gdr@merlin.nerim.net> wrote:
|
| > Gennaro Prota <gennaro_prota@yahoo.com> writes:
|
| > The order in which the temporaries are created is not specified
| > by the standard and there is no way for a conforming program to
| > know that for fundamental types.
|
| Order has nothing to do with it.
I was answering an issue raised by Gennaro on order of temporaries
creation.
| The standard says that when a builtin rvalue is used, a temporary is
| created to bind to the const reference. The conforming program from
| James has observable behavior which will detect whether two or one
| temporaries were created.
Certainly. But does the standard *specify* the order in which the
tempoaries are created? Answer: No.
Does the standard unambigously specify that two distinct temporaries
are created? Answer: Nobody provides so far a definitive quote.
| > The two references are bounded to a created temporary.
|
| Each reference is bound to a created temporary.
I'm not disputing that. Thes question is whether the two temporaries
are required to be distinct, as James claimed.
| The standard says
| that a temporary shall be created. Where do you find anything which
| says that an implementation might not bother if it can reuse some
| other temporary which happens to have the same lifetime?
I find nothing to that effect. But then, there is nothing definite to
the contrary either. That is the whole point of the discussion.
In case there is no explicit description of behaviour, we should
expect undefined behaviour. Hence, my orginal answer in this thread.
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Hyman Rosen <hyrosen@mail.com>
Date: Sun, 16 Jun 2002 04:38:23 GMT Raw View
Gabriel Dos Reis wrote:
> Which is:
>
> Otherwise, a temporary of type cv1 T1 is created and initialized
> from the initializer expression using the rules for a non-reference
> copy initialization (8.5). The reference is then bound to the
> tem-porary. If T1 is reference-related to T2, cv1 must be the same
> cv-qualification as, or greater cv-qualification than, cv2;
> otherwise, the program is ill-formed.
>
> There is nothing in that paragraph that supports your claim.
The program in question is
void f(int const &a, int const &b)
{ std::cout << (&a == &b ? "equal" : "not equal"); }
int main() { f(5, 5); }
and the claim is that this must produce "not equal".
That paragraph in the standard talks about how a reference is
initialized from an expression. It says (under circunstances
matched by the example) that when initializing a reference, a
temporary is created from the initializing expression and the
reference is bound to it. What support do you have for saying
that an implementation is permitted not to do this? In this
program there are two such reference initializations, and thus
two temporaries must be created, and each reference bound to
one of them.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@merlin.nerim.net>
Date: Sun, 16 Jun 2002 07:06:02 GMT Raw View
Hyman Rosen <hyrosen@mail.com> writes:
| Gabriel Dos Reis wrote:
| > Which is:
| >
| > Otherwise, a temporary of type cv1 T1 is created and initialized
| > from the initializer expression using the rules for a non-reference
| > copy initialization (8.5). The reference is then bound to the
| > tem-porary. If T1 is reference-related to T2, cv1 must be the same
| > cv-qualification as, or greater cv-qualification than, cv2;
| > otherwise, the program is ill-formed.
| >
| > There is nothing in that paragraph that supports your claim.
|
| The program in question is
| void f(int const &a, int const &b)
| { std::cout << (&a == &b ? "equal" : "not equal"); }
| int main() { f(5, 5); }
| and the claim is that this must produce "not equal".
I know what the program is. I'm questioning the claim.
| That paragraph in the standard talks about how a reference is
| initialized from an expression.
Agreed.
| It says (under circunstances
| matched by the example) that when initializing a reference, a
| temporary is created from the initializing expression and the
| reference is bound to it. What support do you have for saying
| that an implementation is permitted not to do this?
I'm asking where do you find an explicit requirement that the two
references should be bound to distinct temporaries. In absence of
such explicit description (or unambigous inference) undefined
behaviour should be expected.
| In this
| program there are two such reference initializations, and thus
| two temporaries must be created, and each reference bound to
| one of them.
Actually, that paragraph says a temporary is created and a
reference is bound to that temporary. But that paragraph fails to say
unambigously that two distinct references should be bound to distinct
temporaries -- hence forbidding value sharing. My position is that in the
absence of explicit descrption, an undefined behaviour should be expected.
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: James Kanze <kanze@alex.gabi-soft.de>
Date: Mon, 17 Jun 2002 05:02:38 GMT Raw View
Gabriel Dos Reis <gdr@merlin.nerim.net> writes:
|> Gennaro Prota <gennaro_prota@yahoo.com> writes:
|> [...]
|> | > Since there are two separate bindings, with two separate
|> | >temporary values, it would seem that we have two separate
|> | >objects.
|> | The section you refer to is 8.5.3/5 (emphasis mine): "a
|> | temporary of type "cv1 T1" _is created_ and initialized from the
|> | initializer expression using the rules for a non-reference copy
|> | initialization (8.5). The reference is then bound to the
|> | temporary."
|> | The words "is created" seem not to leave enough space for the
|> | compiler to reuse an already created object when doing the
|> | second binding. Of course I'm assuming that the two bindings
|> | cannot happen simultaneously. Any other opinions? :)
|> Yes, I have one because I think you're reading too much into the
|> standard.
The problem is, I think, that we never actually considered this point
when defining the standard. You can probably read a lot of things
into the standard that weren't meant to be there. But how can you
tell what was actually meant, and what you are reading into it? In
the section Gennaro quotes, the words "is created" are very clear:
when binding an rvalue to a const reference, an "object" is created.
If there are two references, two objects must be created.
Of course, if you read the entire paragraph, it offers an
implementation defined choice, and an implementation may bind "the
object represented by the rvalue [...]". The reference to 3.10, here,
suggests that this option is only relevant to class types -- rvalues
of basic types do not have "objects". But it is far from clear.
|> The order in which the temporaries are created is not specified by
|> the standard and there is no way for a conforming program to know
|> that for fundamental types.
Nobody is arguing about the order. The question is how many?
|> The two references are bounded to a created temporary.
Unless you argue that 5 in my original example is an object (and that
the implementation chooses to bind to a specific object), I think you
are forced to admit one creation per reference. Whatever that means.
A priori, I would interpret the standard to say that the two addresses
in my example must be different. But I rather suspect that the fact
that the standard says this is more accidental than anything else, and
I certainly wouldn't mind a clarification. One way or the other.
(For reference, the orginal program was:
#include <iostream>
#include <ostream>
void
f( int const& a, int const& b )
{
std::cout << (&a =3D=3D &b ? "true" : "false") << '\n' ;
}
int
main()
{
f( 5, 5 ) ;
return 0 ;
}
And the proposition is that on a conforming implementation, this
program *must* output "false".)
--
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)69 63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: James Kanze <kanze@alex.gabi-soft.de>
Date: Mon, 17 Jun 2002 05:02:52 GMT Raw View
Gabriel Dos Reis <gdr@merlin.nerim.net> writes:
|> | In this program there are two such reference initializations,
|> | and thus two temporaries must be created, and each reference
|> | bound to one of them.
|> Actually, that paragraph says a temporary is created and a
|> reference is bound to that temporary. But that paragraph fails to
|> say unambigously that two distinct references should be bound to
|> distinct temporaries -- hence forbidding value sharing. My
|> position is that in the absence of explicit descrption, an
|> undefined behaviour should be expected.
It says that a temporary is created. Thus, two temporaries must be
created (by the abstract machine, at least). There is no language
allowing the compiler to forgo the creation, except possibly the as if
rule.
The text goes on to say that the reference is bound to *the* temporary
(not a temporary, but the temporary just created).
Using just one temporary is an optimization, potentially legal under
the "as if" rule. I have shown a conforming program which can detect
this optimization, however. Thus, the "as if" rule cannot apply.
IMHO, the use of the definite article, and a present, personal form of
the verb "to create", doesn't leave much room for other
intepretations. (On the other hand, I'm not at all sure that the
results were intentional.)
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)69 63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: thp@cs.ucr.edu
Date: Mon, 17 Jun 2002 05:03:24 GMT Raw View
Gabriel Dos Reis <gdr@merlin.nerim.net> wrote:
[...]
: In absence of
: such explicit description (or unambigous inference) undefined
: behaviour should be expected.
[...]
: My position is that in the
: absence of explicit descrption, an undefined behaviour should be expected.
Is it the position of the Standards Committee that behavior should be
considered "undefined" whenever its specification not unambiguous?
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: jpotter@falcon.lhup.edu (John Potter)
Date: Mon, 17 Jun 2002 05:07:49 GMT Raw View
On Sat, 15 Jun 2002 23:16:21 GMT, Gabriel Dos Reis
<gdr@merlin.nerim.net> wrote:
> jpotter@falcon.lhup.edu (John Potter) writes:
> | The standard says that when a builtin rvalue is used, a temporary is
> | created to bind to the const reference. The conforming program from
> | James has observable behavior which will detect whether two or one
> | temporaries were created.
> Does the standard unambigously specify that two distinct temporaries
> are created? Answer: Nobody provides so far a definitive quote.
Everyone but you accepts it.
> | > The two references are bounded to a created temporary.
> | Each reference is bound to a created temporary.
> I'm not disputing that. Thes question is whether the two temporaries
> are required to be distinct, as James claimed.
Simply put, it says that when a fundamental rvalue is bound to a const
reference, a temporary is created. There are two const references which
requires two temporaries. Whenever the standard allows deviation from
something this basic, it states it. Example: copies with all the
allowances for eliding them.
> In case there is no explicit description of behaviour, we should
> expect undefined behaviour. Hence, my orginal answer in this thread.
Undefined behavior is anything. Do you expect it to format your hard
drive, even figuratively? It is clearly not undefined behavior. It is
not implementation defined behavior because the standard always states
what is implementation defined. It is clearly not specified as
unspecified behavior either. There is no "as-if" rule to apply because
there is observable behavior.
Do you have anything to offer other than your insistence?
John
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@codesourcery.com>
Date: Mon, 17 Jun 2002 18:00:30 GMT Raw View
James Kanze <kanze@alex.gabi-soft.de> writes:
[...]
| The problem is, I think, that we never actually considered this point
| when defining the standard.
There are many many points we didn't consider when defining the
standard ;-)
| You can probably read a lot of things
| into the standard that weren't meant to be there. But how can you
| tell what was actually meant, and what you are reading into it?
By asking for clarification? Someone claims that is insistance,
but I fair he missed the point.
You've offered your interpretation, and I thank you for that. That
you also admitted you weren't 100% sure because the passage isn't
clear adds a great value to your interpretation.
But saying my question is just an insistance diminishes the value of
that interpretation. Saying condescendingly that "everyone but you
accepts it" is worse that saying nothing at all. That reminds me of a
defect about std::vector<bool> (the famous std::vector<bool> is not a
container issue) Valentin Bonnard submitted very early, just after the
standard was published. It was responded that that wasn't a defect --
presumaly because everyone accepted it wasn't a defect.
That remains not a defect until Herb and others published papers that
there were a actually defect :-(
| In
| the section Gennaro quotes, the words "is created" are very clear:
| when binding an rvalue to a const reference, an "object" is created.
| If there are two references, two objects must be created.
|
| Of course, if you read the entire paragraph, it offers an
| implementation defined choice, and an implementation may bind "the
| object represented by the rvalue [...]". The reference to 3.10, here,
| suggests that this option is only relevant to class types -- rvalues
| of basic types do not have "objects". But it is far from clear.
If I keep asking for a crystal clear clarification, it is precisely
because I don't find the rules that clear. I'm looking for something
other than "Do you have anything to offer other than your insistence?",
because that answer doesn't offer any clarification.
[...]
| |> The two references are bounded to a created temporary.
|
| Unless you argue that 5 in my original example is an object
I'm certainly not arguing that.
| (and that
| the implementation chooses to bind to a specific object), I think you
| are forced to admit one creation per reference. Whatever that means.
|
| A priori, I would interpret the standard to say that the two addresses
| in my example must be different. But I rather suspect that the fact
| that the standard says this is more accidental than anything else, and
| I certainly wouldn't mind a clarification. One way or the other.
I would certainly welcome a clarification. Not a
"Do you have anything to offer other than your insistence?"
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@merlin.nerim.net>
Date: Mon, 17 Jun 2002 18:00:17 GMT Raw View
jpotter@falcon.lhup.edu (John Potter) writes:
| On Sat, 15 Jun 2002 23:16:21 GMT, Gabriel Dos Reis
| <gdr@merlin.nerim.net> wrote:
|
| > jpotter@falcon.lhup.edu (John Potter) writes:
|
| > | The standard says that when a builtin rvalue is used, a temporary is
| > | created to bind to the const reference. The conforming program from
| > | James has observable behavior which will detect whether two or one
| > | temporaries were created.
|
| > Does the standard unambigously specify that two distinct temporaries
| > are created? Answer: Nobody provides so far a definitive quote.
|
| Everyone but you accepts it.
Does that mean that what is offered is a crystal clear explanation,
even when those who offered their explanations said they weren't sure?
[...]
| It is clearly not specified as unspecified behavior either.
The standard doesn't have to say explicitly that a behaviour is
undefined for that to be. It suffices that it omits a descripion of
an explicit behaviour.
| There is no "as-if" rule to apply because
| there is observable behavior.
Nobody body is disputing that there is an observable behaviour. My
question is whether that observable behaviour is the one required by
the standard.
| Do you have anything to offer other than your insistence?
You should not condescendingly regard my question as a mere instance.
It ask for anything but condescension. Thanks.
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@merlin.nerim.net>
Date: Mon, 17 Jun 2002 18:00:56 GMT Raw View
thp@cs.ucr.edu writes:
| Gabriel Dos Reis <gdr@merlin.nerim.net> wrote:
| [...]
| : In absence of
| : such explicit description (or unambigous inference) undefined
| : behaviour should be expected.
| [...]
| : My position is that in the
| : absence of explicit descrption, an undefined behaviour should be expected.
|
| Is it the position of the Standards Committee that behavior should be
| considered "undefined" whenever its specification not unambiguous?
1.3.12 says:
Undefined behavior may also be expected when this International
Standard omits the description of any explicit definition of
behavior.
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Mon, 17 Jun 2002 18:01:34 GMT Raw View
In article <86d6urzgsn.fsf@alex.gabi-soft.de>, James Kanze
<kanze@alex.gabi-soft.de> writes
>(For reference, the orginal program was:
>
> #include <iostream>
> #include <ostream>
>
> void
> f( int const& a, int const& b )
> {
> std::cout << (&a == &b ? "true" : "false") << '\n' ;
> }
>
> int
> main()
> {
> f( 5, 5 ) ;
> return 0 ;
> }
>
>And the proposition is that on a conforming implementation, this
>program *must* output "false".)
However, if you avoid taking the address I think that only one is
required :-) I.e. you only get two when you look.
--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gennaro Prota <gennaro_prota@yahoo.com>
Date: Mon, 17 Jun 2002 18:02:13 GMT Raw View
On Mon, 17 Jun 2002 05:02:38 GMT, James Kanze
<kanze@alex.gabi-soft.de> wrote:
>The problem is, I think, that we never actually considered this point
>when defining the standard. You can probably read a lot of things
>into the standard that weren't meant to be there. But how can you
>tell what was actually meant, and what you are reading into it? In
>the section Gennaro quotes, the words "is created" are very clear:
>when binding an rvalue to a const reference, an "object" is created.
>If there are two references, two objects must be created.
>
>Of course, if you read the entire paragraph, it offers an
>implementation defined choice, and an implementation may bind "the
>object represented by the rvalue [...]". The reference to 3.10, here,
>suggests that this option is only relevant to class types -- rvalues
>of basic types do not have "objects". But it is far from clear.
It's not *suggested*. It's explicitly stated in the text: "If the
initializer expression is an rvalue, *with T2 a class type*".
Genny.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: thp@cs.ucr.edu
Date: Wed, 12 Jun 2002 18:27:44 GMT Raw View
James Kanze <kanze@alex.gabi-soft.de> wrote:
[...]
: The question is rather, can it ever return EXIT_SUCCESS. We have the
: address of two separate objects (which happen to have the same value)
^^^^^^^^^^^^^^^^^^^^
Coalescing equal-valued const temporaries seems a reasonable optimization.
Does the Standard rule it out?
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.de (James Kanze)
Date: Thu, 13 Jun 2002 16:25:37 GMT Raw View
thp@cs.ucr.edu wrote in message news:<ae7tda$bcd$2@glue.ucr.edu>...
> James Kanze <kanze@alex.gabi-soft.de> wrote:
> [...]
> : The question is rather, can it ever return EXIT_SUCCESS. We have the
> : address of two separate objects (which happen to have the same value)
> ^^^^^^^^^^^^^^^^^^^^
> Coalescing equal-valued const temporaries seems a reasonable
> optimization. Does the Standard rule it out?
Can you write a conforming program which can tell the difference?
In practice, the compiler can coalesce any equal-valued const objects
(temporaries or no) whose address is not taken. In the case of
temporaries of non-class type, the compiler can usually determine very
easily that the address is not taken -- about the only exception is if
the temporary is bound to a reference.
There is an interesting case, however:
void
f( int const& a, int const& b )
{
std::cout << (&a == &b ? "equal" : "not equal") << '\n' ;
}
int
main()
{
f( 5, 5 ) ;
return 0 ;
}
I think that a conforming implementation is required to output "not
equal". Any other opinions?
--
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)69 63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Christopher Eltschka <celtschk@web.de>
Date: Thu, 13 Jun 2002 23:55:59 GMT Raw View
James Kanze <kanze@alex.gabi-soft.de> writes:
> Gabriel Dos Reis <gdr@merlin.nerim.net> writes:
>
> |> Christopher Eltschka <celtschk@web.de> writes:
>
> |> | James Kanze <kanze@alex.gabi-soft.de> writes:
>
> |> | [...]
>
> |> | > Not to mention such simple things as "&static_cast< int const& >( 5 )".
>
> |> | > (Obviously, this sort of code can get you into very deap
> |> | > trouble very quickly. But it is legal.)
>
> |> | Which leads me to the following question:
>
> |> | Given the code
>
> |> | #include <cstdlib>
>
> |> | int main()
> |> | {
> |> | if (&static_cast<int const&>(5) == &static_cast<int const&>(5))
> |> | return EXIT_FAILURE;
> |> | else
> |> | return EXIT_SUCCESS;
> |> | }
>
> |> | May this program return EXIT_FAILURE, or is it only allowed to return
> |> | EXIT_SUCCESS?
>
> |> It may return an EXIT_FAILURE as there is no requirement that the
> |> temporary objects created to hold the values five be the same.
>
> The question is rather, can it ever return EXIT_SUCCESS. We have the
> address of two separate objects (which happen to have the same value)
> -- if they are separate objects, they must have distinct addresses.
Did I miss something?
If they have distinct adresses, then comparison with == should give
false, and therefore the else branch should be taken, which returns
EXIT_SUCCESS.
Now both of your answers would sound reasonable to me if I had written
!= (or alternatively had returned EXIT_SUCCESS in the if branch and
EXIT_FAILURE in the else branch).
Indeed, under this assumption, your question actually is equivalent to
my question...
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@codesourcery.com>
Date: Thu, 13 Jun 2002 23:57:57 GMT Raw View
kanze@gabi-soft.de (James Kanze) writes:
[...]
| There is an interesting case, however:
|
| void
| f( int const& a, int const& b )
| {
| std::cout << (&a == &b ? "equal" : "not equal") << '\n' ;
| }
|
| int
| main()
| {
| f( 5, 5 ) ;
| return 0 ;
| }
|
| I think that a conforming implementation is required to output "not
^^^^^^^^^^^
| equal". Any other opinions?
Again, where do you derive that from?
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Hyman Rosen <hyrosen@mail.com>
Date: Fri, 14 Jun 2002 03:07:35 GMT Raw View
Gabriel Dos Reis wrote:
> kanze@gabi-soft.de (James Kanze) writes:
> | I think that a conforming implementation is required to output "not
> | equal". Any other opinions?
> Again, where do you derive that from?
From the final clause of 8.5.3/5.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.de (James Kanze)
Date: Fri, 14 Jun 2002 14:21:24 GMT Raw View
Gabriel Dos Reis <gdr@codesourcery.com> wrote in message
news:<m38z5ihnoc.fsf@merlin.nerim.net>...
> kanze@gabi-soft.de (James Kanze) writes:
> [...]
> | There is an interesting case, however:
> | void
> | f( int const& a, int const& b )
> | {
> | std::cout << (&a == &b ? "equal" : "not equal") << '\n' ;
> | }
> | int
> | main()
> | {
> | f( 5, 5 ) ;
> | return 0 ;
> | }
> | I think that a conforming implementation is required to output "not
> ^^^^^^^^^^^
> | equal". Any other opinions?
> Again, where do you derive that from?
I don't have my copy of the standard here to cite the exact sections,
but the section describing the semantics of the comparison operator
states that the addresses of distinct objects must compare different,
and the sections which describe binding a temporary (an rvalue) to a
const reference speak of creating an object with a specific lifetime,
etc. Since there are two separate bindings, with two separate
temporary values, it would seem that we have two separate objects.
This is, at any rate, a na ve interpretation, made without access to
the actual standard. Still, if it is wrong, I would like to know why.
--
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)69 63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@merlin.nerim.net>
Date: Sat, 15 Jun 2002 06:17:11 GMT Raw View
Hyman Rosen <hyrosen@mail.com> writes:
| Gabriel Dos Reis wrote:
| > kanze@gabi-soft.de (James Kanze) writes:
| > | I think that a conforming implementation is required to output "not
| > | equal". Any other opinions?
| > Again, where do you derive that from?
|
| From the final clause of 8.5.3/5.
Which is:
Otherwise, a temporary of type cv1 T1 is created and initialized
from the initializer expression using the rules for a non-reference
copy initialization (8.5). The reference is then bound to the
tem-porary. If T1 is reference-related to T2, cv1 must be the same
cv-qualification as, or greater cv-qualification than, cv2;
otherwise, the program is ill-formed.
There is nothing in that paragraph that supports your claim.
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gennaro Prota <gennaro_prota@yahoo.com>
Date: Sat, 15 Jun 2002 06:21:41 GMT Raw View
On Fri, 14 Jun 2002 14:21:24 GMT, kanze@gabi-soft.de (James Kanze)
wrote:
[...]
>
>I don't have my copy of the standard here to cite the exact sections,
>but the section describing the semantics of the comparison operator
>states that the addresses of distinct objects must compare different,
>and the sections which describe binding a temporary (an rvalue) to a
>const reference speak of creating an object with a specific lifetime,
>etc.
Actually, I'm not sure that lifetime, per se, is important here.
Suppose that the compiler creates one single temporary object. Can we
write a conforming program which detects whether there are two
separate destructions or not?
> Since there are two separate bindings, with two separate
>temporary values, it would seem that we have two separate objects.
The section you refer to is 8.5.3/5 (emphasis mine): "a temporary of
type "cv1 T1" _is created_ and initialized from the initializer
expression using the rules for a non-reference copy initialization
(8.5). The reference is then bound to the temporary."
The words "is created" seem not to leave enough space for the compiler
to reuse an already created object when doing the second binding. Of
course I'm assuming that the two bindings cannot happen
simultaneously. Any other opinions? :)
Genny.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: James Kanze <kanze@alex.gabi-soft.de>
Date: Tue, 4 Jun 2002 17:16:45 GMT Raw View
Gabriel Dos Reis <gdr@merlin.nerim.net> writes:
|> Christopher Eltschka <celtschk@web.de> writes:
|> | James Kanze <kanze@alex.gabi-soft.de> writes:
|> | [...]
|> | > Not to mention such simple things as "&static_cast< int const& >(=
5 )".
|> | > (Obviously, this sort of code can get you into very deap
|> | > trouble very quickly. But it is legal.)
|> | Which leads me to the following question:
|> | Given the code
|> | #include <cstdlib>
|> | int main()
|> | {
|> | if (&static_cast<int const&>(5) =3D=3D &static_cast<int const&>(5=
))
|> | return EXIT_FAILURE;
|> | else
|> | return EXIT_SUCCESS;
|> | }
|> | May this program return EXIT_FAILURE, or is it only allowed to retu=
rn
|> | EXIT_SUCCESS?
|> It may return an EXIT_FAILURE as there is no requirement that the
|> temporary objects created to hold the values five be the same.
The question is rather, can it ever return EXIT_SUCCESS. We have the
address of two separate objects (which happen to have the same value)
-- if they are separate objects, they must have distinct addresses.
--=20
James Kanze mailto:kanze@gabi-soft.de
Do you need real expertise in C++? in Java? in OO design?
I am available, see my CV at www.gabi-soft.de
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)69 63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@merlin.nerim.net>
Date: Tue, 4 Jun 2002 13:52:27 CST Raw View
James Kanze <kanze@alex.gabi-soft.de> writes:
| Gabriel Dos Reis <gdr@merlin.nerim.net> writes:
|
| |> Christopher Eltschka <celtschk@web.de> writes:
|
| |> | James Kanze <kanze@alex.gabi-soft.de> writes:
|
| |> | [...]
|
| |> | > Not to mention such simple things as "&static_cast< int const& >( 5 )".
|
| |> | > (Obviously, this sort of code can get you into very deap
| |> | > trouble very quickly. But it is legal.)
|
| |> | Which leads me to the following question:
|
| |> | Given the code
|
| |> | #include <cstdlib>
|
| |> | int main()
| |> | {
| |> | if (&static_cast<int const&>(5) == &static_cast<int const&>(5))
| |> | return EXIT_FAILURE;
| |> | else
| |> | return EXIT_SUCCESS;
| |> | }
|
| |> | May this program return EXIT_FAILURE, or is it only allowed to return
| |> | EXIT_SUCCESS?
|
| |> It may return an EXIT_FAILURE as there is no requirement that the
| |> temporary objects created to hold the values five be the same.
|
| The question is rather, can it ever return EXIT_SUCCESS.
I think I answered the question as worded byt Christopher :-)
| We have the
| address of two separate objects (which happen to have the same value)
| -- if they are separate objects, they must have distinct addresses.
I can't unambigously derive that from formal wordings of the standard.
The Standard says pretty much nothing about temporaries.
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Christopher Eltschka <celtschk@web.de>
Date: Mon, 3 Jun 2002 20:14:32 GMT Raw View
James Kanze <kanze@alex.gabi-soft.de> writes:
[...]
> Not to mention such simple things as "&static_cast< int const& >( 5 )".
>
> (Obviously, this sort of code can get you into very deap trouble very
> quickly. But it is legal.)
Which leads me to the following question:
Given the code
#include <cstdlib>
int main()
{
if (&static_cast<int const&>(5) == &static_cast<int const&>(5))
return EXIT_FAILURE;
else
return EXIT_SUCCESS;
}
May this program return EXIT_FAILURE, or is it only allowed to return
EXIT_SUCCESS?
[...]
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@merlin.nerim.net>
Date: Mon, 3 Jun 2002 17:44:51 CST Raw View
Christopher Eltschka <celtschk@web.de> writes:
| James Kanze <kanze@alex.gabi-soft.de> writes:
|
| [...]
|
| > Not to mention such simple things as "&static_cast< int const& >( 5 )".
| >
| > (Obviously, this sort of code can get you into very deap trouble very
| > quickly. But it is legal.)
|
| Which leads me to the following question:
|
| Given the code
|
| #include <cstdlib>
|
| int main()
| {
| if (&static_cast<int const&>(5) == &static_cast<int const&>(5))
| return EXIT_FAILURE;
| else
| return EXIT_SUCCESS;
| }
|
| May this program return EXIT_FAILURE, or is it only allowed to return
| EXIT_SUCCESS?
It may return an EXIT_FAILURE as there is no requirement that the
temporary objects created to hold the values five be the same.
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "David Thompson" <david.thompson1@worldnet.att.net>
Date: Tue, 28 May 2002 00:46:47 GMT Raw View
James Kanze <kanze@alex.gabi-soft.de> wrote
(and OE still won't quote, sorry):
>>>
thp@cs.ucr.edu writes:
....
|> Good idea. I once wrote a Fortran program that inadvertently
|> incremented the literal 3, after which my output went to the wrong
|> device. ;-)
But that's defined behavior in Fortran:-).
Seriously, all of the Fortran standards since 1966 require the
implementation to regenerate the constant on each use, so it must have
been an old compiler.
<<<
No. All Fortran standards since at least F77 (which was
still spelled FORTRAN), and I'm pretty sure F66 as well,
prohibit assigning to a dummy argument that was passed
from a constant (or expression other than a variable)
(in the sense of 'variable' that includes array.)
A compiler can do whatever it likes if you violate the rules.
_Some_ Ftn compilers have in the past, and I think still do,
'regenerate' such constants, sometimes or always.
But it's a matter of the particular compiler and maybe
the options you specify, not old versus new as such.
--
- David.Thompson 1 now at worldnet.att.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Allan_W@my-dejanews.com (Allan W)
Date: Thu, 16 May 2002 19:07:04 GMT Raw View
> thp@cs.ucr.edu writes:
> |> Good idea. I once wrote a Fortran program that inadvertently
> |> incremented the literal 3, after which my output went to the wrong
> |> device. ;-)
James Kanze <kanze@alex.gabi-soft.de> wrote
> But that's defined behavior in Fortran:-).
>
> Seriously, all of the Fortran standards since 1966 require the
> implementation to regenerate the constant on each use, so it must have
> been an old compiler.
Perhaps like C++'s export for templates, it took a long time for
Fortran compilers to catch up with that requirement?
My introduction to assembly language involved looking at COBOL and
Fortran programs and comparing them to the generated assembly
language. I distinctly remember Fortran-to-assembly creating a
literal value "3" that was used in multiple places throughout the
program... I remember that it was an error to try to modify it.
That was the mid- to late- 1970's.
> And to get vaguely back on subject, K&R C allowed modification of
> string literals, with defined behavior. Even today, some C++
> compilers still support this, for historical reasons.
I knew that "literal" was type char* instead of const char*, for
historical reasons... I didn't know that modifying that literal
was ever supported. Was this before it was legal to combine literals?
(i.e. "literal" might save 8 bytes of storage by re-using the end of
string "not so literal" -- but then if one of them changes, they both
do.)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: James Kanze <kanze@alex.gabi-soft.de>
Date: Thu, 16 May 2002 19:45:36 GMT Raw View
Allan_W@my-dejanews.com (Allan W) writes:
|> > thp@cs.ucr.edu writes:
|> > |> Good idea. I once wrote a Fortran program that
|> > |> inadvertently incremented the literal 3, after which my
|> > |> output went to the wrong device. ;-)
|> James Kanze <kanze@alex.gabi-soft.de> wrote
|> > But that's defined behavior in Fortran:-).
|> > Seriously, all of the Fortran standards since 1966 require the
|> > implementation to regenerate the constant on each use, so it
|> > must have been an old compiler.
|> Perhaps like C++'s export for templates, it took a long time for
|> Fortran compilers to catch up with that requirement?
Or they required special flags to be 100% conform:-). Making a
conforming compiler might break customer code. (Seriously, I think it
was 1966, but it may have been the 1977 standard which made the
change. Before that, it was undefined behavior to modify a constant.)
|> My introduction to assembly language involved looking at COBOL and
|> Fortran programs and comparing them to the generated assembly
|> language. I distinctly remember Fortran-to-assembly creating a
|> literal value "3" that was used in multiple places throughout the
|> program... I remember that it was an error to try to modify it.
|> That was the mid- to late- 1970's.
Then it was probably Fortran 77 that introduced the requirement, and
my memory is slipping.
|> > And to get vaguely back on subject, K&R C allowed modification
|> > of string literals, with defined behavior. Even today, some C++
|> > compilers still support this, for historical reasons.
|> I knew that "literal" was type char* instead of const char*, for
|> historical reasons... I didn't know that modifying that literal
|> was ever supported. Was this before it was legal to combine
|> literals? (i.e. "literal" might save 8 bytes of storage by
|> re-using the end of string "not so literal" -- but then if one of
|> them changes, they both do.)
>From the reference part of K&R I: "All strings, even wehn written
identically, are distinct." A string constant is defined as being an
array of characters, with storage class static, *initialized* with the
given characters. I have vague memories of an explicit statement
saying that modifying such a literal was legal and defined, but I
can't find it off hand; there is, however, nothing that gives the
slightest indication that a string literal behaves in any way
differently than an array of char, i.e. a char[], and the use of
"initialized" (rather than "having the value of") may be significant.
The point was apparently discussed in the C standardization; reading
of 3.1.4 in the C Rationale gives some interesting sidelights. (See
http://www.lysator.liu.se/c/rat/title.html.)
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: James Kanze <kanze@alex.gabi-soft.de>
Date: Mon, 13 May 2002 17:22:26 GMT Raw View
Gabriel Dos_Reis <gdosreis@sophia.inria.fr> writes:
|> James Kanze <kanze@alex.gabi-soft.de> writes:
|> [...]
|> | |> However I agree that the situtation would be better if we
|> | |> expressed lvalueness directly in the type-system (using
|> | |> references for example).
|> | Or simply doing away with it entirely. What's really wrong with
|> | allowing "&3"?
|> Hum, it turns "3" into an object and we don't really want that ;-)
Why not? Then we could claim to be more object oriented than Java:-).
Seriously, the only real problem I see is the lifetime of temporaries
issue. And the question of the actual type -- when I suggested this,
my idea was that temporaries have a const type, so that "&3" would
have the type int const*. This, of course, would mean that "T()" also
has a type T const&. This is not conform with the current standard.
|> Seriously, were lvalueness directly expressed in the type system,
|> you won't run into embarassing situation where type-deduction of
|> an expression loses its lvaluness attribute :-(
Right. And you could overload on it for user defined operators.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: thp@cs.ucr.edu
Date: Mon, 13 May 2002 20:52:20 GMT Raw View
James Kanze <kanze@alex.gabi-soft.de> wrote:
[...]
: when I suggested this,
: my idea was that temporaries have a const type, so that "&3" would
: have the type int const*.
Good idea. I once wrote a Fortran program that inadvertently
incremented the literal 3, after which my output went to the wrong
device. ;-)
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: James Kanze <kanze@alex.gabi-soft.de>
Date: Tue, 14 May 2002 17:54:06 GMT Raw View
thp@cs.ucr.edu writes:
|> James Kanze <kanze@alex.gabi-soft.de> wrote:
|> [...]
|> : when I suggested this,
|> : my idea was that temporaries have a const type, so that "&3" would
|> : have the type int const*. =20
|> Good idea. I once wrote a Fortran program that inadvertently
|> incremented the literal 3, after which my output went to the wrong
|> device. ;-)
But that's defined behavior in Fortran:-).
Seriously, all of the Fortran standards since 1966 require the
implementation to regenerate the constant on each use, so it must have
been an old compiler.
And to get vaguely back on subject, K&R C allowed modification of
string literals, with defined behavior. Even today, some C++
compilers still support this, for historical reasons.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos_Reis <gdosreis@sophia.inria.fr>
Date: Fri, 10 May 2002 19:44:16 GMT Raw View
James Kanze <kanze@alex.gabi-soft.de> writes:
[...]
| |> However I agree that the situtation would be better if we
| |> expressed lvalueness directly in the type-system (using references
| |> for example).
|
| Or simply doing away with it entirely. What's really wrong with
| allowing "&3"?
Hum, it turns "3" into an object and we don't really want that ;-)
Seriously, were lvalueness directly expressed in the type system, you
won't run into embarassing situation where type-deduction of an
expression loses its lvaluness attribute :-(
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: James Kanze <kanze@alex.gabi-soft.de>
Date: Thu, 2 May 2002 17:07:41 GMT Raw View
thp@cs.ucr.edu writes:
|> James Kanze <kanze@alex.gabi-soft.de> wrote:
|> [...]
|> : First, only expressions are lvalues or rvalues -- an object is,
|> : in itself, neither.
|> : Given that, the result of an expression is an lvalue if the
|> : standard says it is an lvalue, and it is an rvalue if the
|> : standard says it is an rvalue. Historically, the idea was that
|> : an lvalue designates an object in memory, and the choice of
|> : which operators return lvalues (and which ones require them) is
|> : based on this historical concept. But the language has evolved,
|> : and this distinction is less clear -- as the standard says, in
|> : certain contexts, some rvalues must have fixed addresses in
|> : memory as well. And it is possible to obtain the address of an
|> : rvalue. So all that is really left is an artificial
|> : distinction.
|> Conjecture: an expression E is an lvalue if and only if &E is a
|> valid expression.
That's a pleonasm. The standard requires that the operand of the
built-in operator & be an lvalue.
Of course, if there is a user defined operator&, then &E may be valid
even if E is an rvalue, e.g.:
struct C
{
C* operator&() { return this ; }
}
C* pc =3D &C() ;
Not to mention such simple things as "&static_cast< int const& >( 5 )".
(Obviously, this sort of code can get you into very deap trouble very
quickly. But it is legal.)
|> That conjecture, if correct, seems to capture the fundamental
|> surviving distinction between lvalues and rvalues.
Sort of. The standard specifies places where lvalues are required,
and IMHO, that specification is part of the definition of an lvalue.
It also specifies whether a given expression returns an lvalue or not
-- I find that this is an even more important aspect of the
definition.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
Date: Thu, 2 May 2002 17:08:29 GMT Raw View
thp@cs.ucr.edu writes:
| James Kanze <kanze@alex.gabi-soft.de> wrote:
| [...]
| : First, only expressions are lvalues or rvalues -- an object is, in
| : itself, neither.
|
| : Given that, the result of an expression is an lvalue if the standard
| : says it is an lvalue, and it is an rvalue if the standard says it is
| : an rvalue. Historically, the idea was that an lvalue designates an
| : object in memory, and the choice of which operators return lvalues
| : (and which ones require them) is based on this historical concept.
| : But the language has evolved, and this distinction is less clear -- as
| : the standard says, in certain contexts, some rvalues must have fixed
| : addresses in memory as well. And it is possible to obtain the address
| : of an rvalue. So all that is really left is an artificial
| : distinction.
|
| Conjecture: an expression E is an lvalue if and only if &E is a valid
| expression.
struct X {
X* operator&() const { return this; }
};
Given that, is X() an lvalue? No, according to the standard.
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
Date: Thu, 2 May 2002 20:05:59 GMT Raw View
James Kanze <kanze@alex.gabi-soft.de> writes:
[...]
| So all that is really left is an artificial distinction.
I don't think it is that artificial as you're implying. Some
expression just aren't rvalue as 1 + 4.
However I agree that the situtation would be better if we expressed
lvalueness directly in the type-system (using references for example).
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: James Kanze <kanze@alex.gabi-soft.de>
Date: Fri, 3 May 2002 20:54:03 GMT Raw View
Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr> writes:
|> James Kanze <kanze@alex.gabi-soft.de> writes:
|> [...]
|> | So all that is really left is an artificial distinction.
|> I don't think it is that artificial as you're implying. Some
|> expression just aren't rvalue as 1 + 4.
And some are, like static_cast< int const& >( 4 ) :-).
There is an underlying rationale concerning which expressions are
lvalues, and which aren't. But that rationale is really based on a
situation before there were classes (or even structs) and before there
was const. (Remember that in the beginning, it was guaranteed that
all string literals were separate, and modifying one was allowed and
had defined behavior.)
|> However I agree that the situtation would be better if we
|> expressed lvalueness directly in the type-system (using references
|> for example).
Or simply doing away with it entirely. What's really wrong with
allowing "&3"?
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: jpotter@falcon.lhup.edu (John Potter)
Date: Tue, 30 Apr 2002 17:19:59 CST Raw View
On Tue, 30 Apr 2002 21:23:30 GMT, thp@cs.ucr.edu wrote:
> James Kanze <kanze@alex.gabi-soft.de> wrote:
> [...]
> : First, only expressions are lvalues or rvalues -- an object is, in
> : itself, neither.
>
> : Given that, the result of an expression is an lvalue if the standard
> : says it is an lvalue, and it is an rvalue if the standard says it is
> : an rvalue. Historically, the idea was that an lvalue designates an
> : object in memory, and the choice of which operators return lvalues
> : (and which ones require them) is based on this historical concept.
> : But the language has evolved, and this distinction is less clear -- as
> : the standard says, in certain contexts, some rvalues must have fixed
> : addresses in memory as well. And it is possible to obtain the address
> : of an rvalue. So all that is really left is an artificial
> : distinction.
>
> Conjecture: an expression E is an lvalue if and only if &E is a valid
> expression.
Close, but no banana.
struct S {
int operator& () const { return 42; }
};
class C {
void operator& ();
};
int main () {
cout << &S() << endl; // valid on rvalue
C c;
&c; // invalid on lvalue
}
How about
T& t(E);
Conjecture: An expression E is an lvalue if and only if it may be used
to initialize a non-const reference.
> That conjecture, if correct, seems to capture the fundamental
> surviving distinction between lvalues and rvalues.
John
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: thp@cs.ucr.edu
Date: Wed, 1 May 2002 00:26:32 GMT Raw View
John Potter <jpotter@falcon.lhup.edu> wrote:
[...]
: struct S {
: int operator& () const { return 42; }
: };
: class C {
: void operator& ();
: };
: int main () {
: cout << &S() << endl; // valid on rvalue
: C c;
: &c; // invalid on lvalue
: }
Agreed.
: How about
: T& t(E);
: Conjecture: An expression E is an lvalue if and only if it may be used
: to initialize a non-const reference.
Agreed.
So, what is the point to maintaining the distinction between "rvalue"
and "lvalue"? (The prohibition on initializing non-const references
from rvalues is a bit artificial.)
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "Hillel Y. Sims" <usenet@phatbasset.com>
Date: Wed, 1 May 2002 17:08:13 GMT Raw View
I got this message on my EDG-based compiler:
struct A {};
void func(A&);
void func2()
{
func(A());
}
func(A());
..........^
%CXX-E-REFTEMPORARY, initial value of reference to non-const must be an
lvalue
hys
"John Potter" <jpotter@falcon.lhup.edu> wrote in message
news:3ccf16c6.15745312@news.earthlink.net...
> How about
>
> T& t(E);
>
> Conjecture: An expression E is an lvalue if and only if it may be used
> to initialize a non-const reference.
>
--
Hillel Y. Sims
hsims AT factset.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: jpotter@falcon.lhup.edu (John Potter)
Date: Wed, 1 May 2002 17:12:13 GMT Raw View
On Wed, 1 May 2002 00:26:32 GMT, thp@cs.ucr.edu wrote:
> John Potter <jpotter@falcon.lhup.edu> wrote:
> : Conjecture: An expression E is an lvalue if and only if it may be used
> : to initialize a non-const reference.
>
> Agreed.
>
> So, what is the point to maintaining the distinction between "rvalue"
> and "lvalue"? (The prohibition on initializing non-const references
> from rvalues is a bit artificial.)
There are no rvalues of type array. If we go back to pre-standard C,
there were no rvalues of type struct. Rvalues make sense for
fundamental types. Rvalues for UDTs make amusing newsgroup threads.
John
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Michiel.Salters@cmg.nl (Michiel Salters)
Date: Wed, 1 May 2002 17:15:39 GMT Raw View
jpotter@falcon.lhup.edu (John Potter) wrote in message news:<3ccf16c6.15745312@news.earthlink.net>...
> On Tue, 30 Apr 2002 21:23:30 GMT, thp@cs.ucr.edu wrote:
[ SNIP ]
> How about
>
> T& t(E);
>
> Conjecture: An expression E is an lvalue if and only if it may be used
> to initialize a non-const reference.
Close, but still no banana :
const int E = 0;
int& ri ( E );
Not to mention volatile.
I thought of: "An expression E is an lvalue iff it may be used to
initialize a reference which has the same type and cv-qualifiers as E"
but I'm not sure about cv-qualifiers on rvalues.
Regards,
--
Michiel Salters
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: jpotter@falcon.lhup.edu (John Potter)
Date: Wed, 1 May 2002 21:07:48 GMT Raw View
On Wed, 1 May 2002 17:08:13 GMT, "Hillel Y. Sims"
<usenet@phatbasset.com> wrote:
> I got this message on my EDG-based compiler:
>
> struct A {};
> void func(A&);
> void func2()
> {
> func(A());
> }
>
> func(A());
> ..........^
> %CXX-E-REFTEMPORARY, initial value of reference to non-const must be an
> lvalue
I seem to be missing your point. A() is an rvalue and may not be the
initial value of a non-const reference. Which is what I said.
> "John Potter" <jpotter@falcon.lhup.edu> wrote in message
> news:3ccf16c6.15745312@news.earthlink.net...
> > Conjecture: An expression E is an lvalue if and only if it may be used
> > to initialize a non-const reference.
John
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: jpotter@falcon.lhup.edu (John Potter)
Date: Wed, 1 May 2002 22:00:37 GMT Raw View
On Wed, 1 May 2002 17:15:39 GMT, Michiel.Salters@cmg.nl (Michiel
Salters) wrote:
> jpotter@falcon.lhup.edu (John Potter) wrote in message news:<3ccf16c6.15745312@news.earthlink.net>...
> > On Tue, 30 Apr 2002 21:23:30 GMT, thp@cs.ucr.edu wrote:
> [ SNIP ]
> > How about
> >
> > T& t(E);
> >
> > Conjecture: An expression E is an lvalue if and only if it may be used
> > to initialize a non-const reference.
> Close, but still no banana :
Half a banana? I got the if part. ;)
> const int E = 0;
> int& ri ( E );
> Not to mention volatile.
Yep. Nice.
> I thought of: "An expression E is an lvalue iff it may be used to
> initialize a reference which has the same type and cv-qualifiers as E"
> but I'm not sure about cv-qualifiers on rvalues.
Fundamental rvalues have no cv-qualifiers. UDT rvalues may have
cv-qualifiers. An rvalue const could initialize a const reference.
I wanna banana :)
Conjecture: An expression E is an lvalue iff the expression
const_cast<T&>(E) is well formed.
It only needs to be well formed, undefined behavior does not disqualify
the conjecture.
Axiom: An expression E is an lvalue iff the standard says so.
No banana for that.
John
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Claus Rasmussen <clr@cc-consult.dk>
Date: Mon, 29 Apr 2002 17:48:24 GMT Raw View
John the newbie wrote:
> I believed that an l-value is an expression that refers something in
> memory (even if its content is non-modifiable) and that an r-value is
> anything that isn't an l-value. Anyhow section 3.10 of the standard
> states:
An l-value can appear on the left side of the assignment operator. This
has the implication that l-values always refer to memory locatations but
it is a logical fallacy to conclude that it means that r-values are newer
referring to a memory locations.
Simple example:
int l;
const int r = 42;
l = r;
Here l is a l-value and r is a r-value referring to a memory location.
-Claus
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Ron Natalie <ron@sensor.com>
Date: Mon, 29 Apr 2002 18:08:28 GMT Raw View
Claus Rasmussen wrote:
> An l-value can appear on the left side of the assignment operator. This
> has the implication that l-values always refer to memory locatations but
> it is a logical fallacy to conclude that it means that r-values are newer
> referring to a memory locations.
>
> Simple example:
>
> int l;
> const int r = 42;
>
> l = r;
>
> Here l is a l-value and r is a r-value referring to a memory location.
>
Sorry, r is an l-value as well. Just because something is an l-value
doesn't mean it's modifiable by assignment. const-ness doesn't affect
l-value-ness.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: jpotter@falcon.lhup.edu (John Potter)
Date: Mon, 29 Apr 2002 19:40:02 GMT Raw View
On Mon, 29 Apr 2002 17:48:24 GMT, Claus Rasmussen <clr@cc-consult.dk>
wrote:
> John the newbie wrote:
>
> > I believed that an l-value is an expression that refers something in
> > memory (even if its content is non-modifiable) and that an r-value is
> > anything that isn't an l-value. Anyhow section 3.10 of the standard
> > states:
>
> An l-value can appear on the left side of the assignment operator. This
> has the implication that l-values always refer to memory locatations but
> it is a logical fallacy to conclude that it means that r-values are newer
> referring to a memory locations.
>
> Simple example:
>
> int l;
> const int r = 42;
r is a non-modifiable l-value.
const int* p = &r;
The unary & requires an l-value
> l = r;
>
> Here l is a l-value and r is a r-value referring to a memory location.
The standard conversion l-value to r-value is performed on the l-value r
to give its r-value.
I think the OP understands this part. The hard part is that r-values of
class type can be modifiable and look like l-values.
struct S { };
S* p = & S(); // error l-value required.
S() = S(); // no error
That is S().operator=(S());
The r-value on the left is assigned using the member operator=. There
are modifiable r-values.
John
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: agriff@tin.it (Andrea Griffini)
Date: Mon, 29 Apr 2002 21:03:33 GMT Raw View
On Mon, 29 Apr 2002 17:48:24 GMT, Claus Rasmussen <clr@cc-consult.dk>
wrote:
>An l-value can appear on the left side of the assignment operator.
And an r-value too... so this is not much of a clarification...
struct X {};
void foo()
{
X() = X(); // Legal
}
In my unofficial docs I read in 3.10/6 [basic.lval]
"An expression which holds a temporary object
resulting from a cast to a nonreference type
is an rvalue (this includes the explicit
creation of an object using functional
notation (_expr.type.conv_))."
So the X() on the left side of the assigment operator
is an r-value, but nothing prevents calling
X::operator=() on that instance.
Looks like that despite those "l"/"r" initials, both
l-values and r-values are allowed on both sides of
an assignment operator...
Andrea
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: James Kanze <kanze@alex.gabi-soft.de>
Date: Tue, 30 Apr 2002 16:45:26 GMT Raw View
whatiscpp@yahoo.com (John the newbie) writes:
|> I believed that an l-value is an expression that refers something
|> in memory (even if its content is non-modifiable) and that an
|> r-value is anything that isn't an l-value. Anyhow section 3.10 of
|> the standard states:
|> "Every expression is either an lvalue or an rvalue. An lvalue
|> refers to an object or function. Some rvalue expressions---those
|> of class or cv-qualified class type---also refer to objects".
First, only expressions are lvalues or rvalues -- an object is, in
itself, neither.
Given that, the result of an expression is an lvalue if the standard
says it is an lvalue, and it is an rvalue if the standard says it is
an rvalue. Historically, the idea was that an lvalue designates an
object in memory, and the choice of which operators return lvalues
(and which ones require them) is based on this historical concept.
But the language has evolved, and this distinction is less clear -- as
the standard says, in certain contexts, some rvalues must have fixed
addresses in memory as well. And it is possible to obtain the address
of an rvalue. So all that is really left is an artificial
distinction.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: James Kanze <kanze@alex.gabi-soft.de>
Date: Tue, 30 Apr 2002 16:45:41 GMT Raw View
Claus Rasmussen <clr@cc-consult.dk> writes:
|> John the newbie wrote:
|> > I believed that an l-value is an expression that refers
|> > something in memory (even if its content is non-modifiable) and
|> > that an r-value is anything that isn't an l-value. Anyhow
|> > section 3.10 of the standard states:
|> An l-value can appear on the left side of the assignment
|> operator.=20
You mean like string literals (which are lvalues).
|> This has the implication that l-values always refer to memory
|> locatations but it is a logical fallacy to conclude that it means
|> that r-values are newer referring to a memory locations.
|> Simple example:
|> int l; =20
|> const int r =3D 42;
|> l =3D r;
|> Here l is a l-value and r is a r-value referring to a memory
|> location.
The expression 'r' is also an l-value. Since assignment requires an
r-value on the right hand side, an l-value to r-value conversion takes
place.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: thp@cs.ucr.edu
Date: Tue, 30 Apr 2002 21:23:30 GMT Raw View
James Kanze <kanze@alex.gabi-soft.de> wrote:
[...]
: First, only expressions are lvalues or rvalues -- an object is, in
: itself, neither.
: Given that, the result of an expression is an lvalue if the standard
: says it is an lvalue, and it is an rvalue if the standard says it is
: an rvalue. Historically, the idea was that an lvalue designates an
: object in memory, and the choice of which operators return lvalues
: (and which ones require them) is based on this historical concept.
: But the language has evolved, and this distinction is less clear -- as
: the standard says, in certain contexts, some rvalues must have fixed
: addresses in memory as well. And it is possible to obtain the address
: of an rvalue. So all that is really left is an artificial
: distinction.
Conjecture: an expression E is an lvalue if and only if &E is a valid
expression.
That conjecture, if correct, seems to capture the fundamental
surviving distinction between lvalues and rvalues.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: whatiscpp@yahoo.com (John the newbie)
Date: Mon, 29 Apr 2002 16:58:15 GMT Raw View
Hi everybody,
I know this is actually a FAQ and I thought to know the answer, until
I looked some definitions in the standard.
I believed that an l-value is an expression that refers something in
memory (even if its content is non-modifiable) and that an r-value is
anything that isn't an l-value. Anyhow section 3.10 of the standard
states:
"Every expression is either an lvalue or an rvalue.
An lvalue refers to an object or function. Some rvalue
expressions---those of class or cv-qualified class type---also refer
to objects".
So it seems that I have the wrong definition of both r-value and
l-value.
Please, can someone explain?
Thanks!!!
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]