Topic: Non-const, L-value temporary


Author: "Tom Widmer" <tom_usenet@hotmail.com>
Date: Tue, 11 Jul 2006 10:41:05 CST
Raw View
Bronek Kozicki wrote:
> Tom Widmer wrote:
> >> following code compiles successfully on strictest compiler available to me
> >> (como 4.3.4.1 -A , ie. strict errors).
> >
> > I think this is an EDG bug.
>
> I'm pretty certain that it is not a bug and compiler is free not to use copy
> constructor ("cctor" for brevity), as explicitly stated in clause 8.5.3
> ("reference is bound in one of the following ways (the choice is
> implementation-defined)").

The problematic code doesn't involve any reference binding:
foo bar() {return foo();}

That involves returning an rvalue (since there return type is not a
reference), and hence the creation of a temporary copy of foo() (unless
it is elided due to 12.8/15).

 This choice has nothing to do with cctor elision as
> described in clause 12.8/15 ; it is simply not used at all, if vendor choose
> so. Also, clause 12.2/1 does not mandate creation of such temporaries; it only
> describes program behaviour if they are actually used. Futhermore ...

Yes, I believe that 12.2/1 only covers temporaries that may be elided
by 12.8/15. This is such a case.

[snip other stuff I agree with, but which applies to the binding of the
returned value to the reference, which has implementation defined
behaviour, not to the creation of the return value, the behaviour of
which is not implementation defined].

Tom

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: brok@rubikon.pl (Bronek Kozicki)
Date: Tue, 11 Jul 2006 21:13:00 GMT
Raw View
Tom Widmer wrote:
>> I'm pretty certain that it is not a bug and compiler is free not to use copy
>> constructor ("cctor" for brevity), as explicitly stated in clause 8.5.3
>> ("reference is bound in one of the following ways (the choice is
>> implementation-defined)").
>
> The problematic code doesn't involve any reference binding:
> foo bar() {return foo();}

Indeed, you are right. Returning by value involves cctor, thus code is ill-formed

> [snip other stuff I agree with, but which applies to the binding of the
> returned value to the reference, which has implementation defined
> behaviour, not to the creation of the return value, the behaviour of
> which is not implementation defined].

yup, these are two different things related to cctor.


B.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: johnchx2@yahoo.com
Date: Tue, 11 Jul 2006 16:14:11 CST
Raw View
Bronek Kozicki wrote:

> Even though it would be defined even if cctor is elided (as
> stated therein), clause 8.5.3 explicitly gives implementor choice not to use
> cctor *at all*. I cannot see anything that mandates definition of implicit
> cctor if it is not used (in the sense of 8.5.3, bullet "The reference is bound
> to the object represented by the rvalue..."), nor anything that mandates
> access checks to subobjects in such situation.

8.5.3/5 says, "The constructor that would be used to make the copy
shall be callable whether or not the copy is actually done."  The
indentation of this sentence implies that it "belongs" to the
surrounding "bullet" and thus applies to both "sub-bullets" (i.e. to
both the direct binding and bind-to-copy option).  The fact that the
copy ctor must be callable whether or not the implementation opts ot
make a copy was -- I gather -- a major motivation for changing this
section (and junking the whole make-a-copy option).

Note that it says "callable," rather than "accessible."  As I read it,
"callable" is a stronger condition.  It might not require the
implicitly-declared copy ctor to be defined, but it might reasonably be
read as requiring the compiler to verify that it could define the copy
ctor if it needed to.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: brok@rubikon.pl (Bronek Kozicki)
Date: Tue, 11 Jul 2006 21:33:39 GMT
Raw View
johnchx2@yahoo.com wrote:
> Note that it says "callable," rather than "accessible."  As I read it,
> "callable" is a stronger condition.  It might not require the
> implicitly-declared copy ctor to be defined, but it might reasonably be
> read as requiring the compiler to verify that it could define the copy
> ctor if it needed to.

it might, or might not. I do not think it is reasonable to expect that
compiler will check "callabality" beyond declaration. This is quite vague
term, luckily now removed. I only hope that vendors will implement new wording
of clause 8.5.3 really soon (and document it).

There is, however, another problem with this code, as Tom noticed - calling
cctor inside body of bar()


B.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Fri, 7 Jul 2006 03:34:10 GMT
Raw View
brok@rubikon.pl ("Bronek Kozicki") writes:

> David Abrahams <dave@boost-consulting.com> wrote:
>> If a compiler does not create the copy,
>> that's simply the way the undefined behavior is expressed on that
>> implementation.
>
> I do not understand your logic. UB is *result* of a copy (without
> copy, string is non-const, and UB is result of applying
> const_cast<string&> on a const string) and not its
> manifestation. Nothing in the standard (before that copy happens)
> suggest that there might be UB (caused by any something else that a
> copy).

Okay, let's put it this way: an implementation is not required to
document whether it makes the copy, therefore one has to assume that
in any given situation, it might make the copy (tests to the contrary
prove nothing about a program whose source differs by as much as an
extra space character).

--
Dave Abrahams
Boost Consulting
www.boost-consulting.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.comeaucomputing.com/csc/faq.html                      ]





Author: jdennett@acm.org (James Dennett)
Date: Fri, 7 Jul 2006 03:34:26 GMT
Raw View
Bronek Kozicki wrote:
> David Abrahams <dave@boost-consulting.com> wrote:
>> If a compiler does not create the copy,
>> that's simply the way the undefined behavior is expressed on that
>> implementation.
>
> I do not understand your logic. UB is *result* of a copy (without copy,
> string is non-const, and UB is result of applying const_cast<string&> on
> a const string) and not its manifestation. Nothing in the standard
> (before that copy happens) suggest that there might be UB (caused by any
> something else that a copy).

If the code contains undefined behavior (which is independent
of how some implementation might choose to optimize it) then
the implementation is unconstrained by the standard.  If a
compiler is permitted by the standard to make a copy, and
the standard says that doing so would give undefined behavior,
then there *is* undefined behavior in that code, as the
standard does not define its result at all.

As Dave notes, it may be that your compiler documents the
behavior it actually implements in this situation, in which
case you're free to use it.  But if it only documents that
it will not make a copy, then it's still free to refuse to
compile the code, as the standard doesn't say anything about
what happens when compiling code which includes UB.

-- James

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: brok@rubikon.pl ("Bronek Kozicki")
Date: Fri, 7 Jul 2006 13:00:17 GMT
Raw View
James Dennett <jdennett@acm.org> wrote:
> If a
> compiler is permitted by the standard to make a copy, and
> the standard says that doing so would give undefined behavior,
> then there *is* undefined behavior in that code, as the

No. Standard does not define whether there is UB or not, as it depends
on how binding rvalues to const reference is implemented by the
compiler, and standard explicitly grants freedom to compiler vendors to
make a copy or not. Thus it is *implementation defined* if there is
undefined behaviour or not.

> standard does not define its result at all.

Indeed, but there is slight difference between implementation defined
behaviour or undefined behaviour. Especially in the light of the fact
that apparently NO compiler makes that copy and that freedom will be
taken away in the next release of the standard.


B.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: "Martin Bonner" <martinfrompi@yahoo.co.uk>
Date: Fri, 7 Jul 2006 09:18:51 CST
Raw View
Frederick Gotham wrote:
> "Bronek Kozicki" posted:
>
>
> >> The code above exhibits undefined behavior.  8.5.3/5 indicates that
> >> the compiler is allowed to introduce a temporary of type const string
> >> and bind the reference cr to that object.
> >
> > The above code *would* expose undefined behaviour, had the compiler
> > actually make such copy. No compiler does that, thus there is no UB.
I disagree.
>
>
> comp.std.c++ is only concerned with fully-portable, Standard-compliant
> code.

It has a wider remit than that.
>
> The Standard decrees that the code has the potential to invoke undefined
> behaviour.
No.  It decrees that it DOES invoke undefined behaviour.

[snip]
> The following doesn't invoke UB on my own computer:
>
>     int i;
>     int s = i;

Yes it does.

I think the point that both you and Bronek have missed is that "invokes
undefined behaviour" does /not/ mean "bad stuff happens".  It means
"the standard doesn't mandate what happens".  In many cases you may
well get the behaviour you wanted - but you can't rely on the standard
to guarantee that.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: johnchx2@yahoo.com
Date: Fri, 7 Jul 2006 09:38:40 CST
Raw View
Niklas Matthies wrote:
> On 2006-07-06 16:41, johnchx2@yahoo.com wrote:
> :
> > In the case of a class with a copy-ctor with observable effects, you
> > might be able to extract some kind of guaranteed behavior, but it would
> > be along the lines of "if the copy-ctor isn't called, the code will
> > behave as expected; otherwise it may do anything at all, including
> > calling the copy-ctor."
>
> Don't you mean "...including NOT calling the copy-ctor"?
>

Oops!  Yes, that's what I meant.

The consequence being that there is literally no possible observable
behavior which is inconsistent with the requirements of the standard,
which is the very definition of undefined behavior (i.e. behavior on
which the standard places no restictions).

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: johnchx2@yahoo.com
Date: Fri, 7 Jul 2006 09:34:08 CST
Raw View
"Bronek Kozicki" wrote:

> Thus it is *implementation defined* if there is
> undefined behaviour or not.

Aha!  Good point.  An implementation is required to document whether it
makes a copy or not (8.5.3/5 makes this implementation defined, *not*
unspecified).  So, I should have said that the code in question was
non-portable, not that it necessarily exhibits undefined behavior.

In any event, the point is largely moot as a practical matter, since
the working draft eliminates the "optional copy" language, and since I
agree that no implementation I'm aware of actually avails itself of the
option to make a copy.

I'm curious to know whether any implementations actually *do*
explicitly document the fact that they don't make a copy in this
situation.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: kuyper@wizard.net
Date: Fri, 7 Jul 2006 13:28:38 CST
Raw View
Martin Bonner wrote:
> Frederick Gotham wrote:
.
> > The Standard decrees that the code has the potential to invoke undefined
> > behaviour.
> No.  It decrees that it DOES invoke undefined behaviour.

No, it decrees conditions for the behavior to be undefined, which for a
particular piece of code may depend upon unspecified and
implementation-defined characteristics of the implementation. On an
implementation which documents that those characteristics are such that
the code in question avoids undefined behavior, then it  had defined
behavior - for that implementation. Implementation-defined behavior is
not merely defined by the implementation's documentation; it must also
be correctly defined by that documentation. And if it is defined in a
way that prevents the code from having undefined behavior, and
implementation can't make use of the fact that a different
implementation's definition would allow undefined behavior as a
justification for violating the requirements set out by the standard
for that code when it's behavior is defined.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: brok@rubikon.pl (Bronek Kozicki)
Date: Fri, 7 Jul 2006 22:40:14 GMT
Raw View
David Abrahams wrote:
> Okay, let's put it this way: an implementation is not required to
> document whether it makes the copy, therefore one has to assume that
> in any given situation, it might make the copy

agreed; but the implementation may actually document that there is no copy.
You are right that it is not specified whether behaviour is well-defined or
not. This is actually worse, as for the same reason but in different
situation, it is not even specified whether program is well-formed or not (see
my other post in this thread, posted minutes before this one). Fortunatelly
this wart is removed by resolution of CWG issue 391.


B.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: brok@rubikon.pl (Bronek Kozicki)
Date: Sat, 8 Jul 2006 01:58:12 GMT
Raw View
Martin Bonner wrote:
>> The Standard decrees that the code has the potential to invoke undefined
>> behaviour.
> No.  It decrees that it DOES invoke undefined behaviour.

no, the code does no invoke undefined behaviour for the same reason for which
following code compiles successfully on strictest compiler available to me
(como 4.3.4.1 -A , ie. strict errors).

class noncopyable
{
   noncopyable(const noncopyable&);
public:
   noncopyable() {}
};

class foo : noncopyable
{};

foo bar() {return foo();}

int main()
{
   const foo& f = bar();
}

.. and the reason is that standard does NOT mandate copy when binding result
of bar() to f , it just allows it. Only when implementation actually makes
such a copy, implicit copy constructor of class foo would have been defined,
thus rendering program ill-formed. If there is a copy or not is implementation
defined, thus it is also implementation defined if above code is well-formed
or not, or wheather casting-away const from f would invoke UB or not.

> I think the point that both you and Bronek have missed is that "invokes
> undefined behaviour" does /not/ mean "bad stuff happens".  It means
> "the standard doesn't mandate what happens".  In many cases you may

I'm not that naiive. Regards


B.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Sat, 8 Jul 2006 14:25:53 GMT
Raw View
brok@rubikon.pl (Bronek Kozicki) writes:

> David Abrahams wrote:
>> Okay, let's put it this way: an implementation is not required to
>> document whether it makes the copy, therefore one has to assume that
>> in any given situation, it might make the copy
>
> agreed; but the implementation may actually document that there is no
> copy. You are right that it is not specified whether behaviour is
> well-defined or not.

Actually not; as pointed out elsewhere 8.5.3/5 requires that it be
implementation-defined whether the copy is made.  I was wrong.

This is a really unusual case in the standard.

> This is actually worse, as for the same reason
> but in different situation, it is not even specified whether program
> is well-formed or not (see my other post in this thread, posted
> minutes before this one).

I might be wrong again, but I can't agree about the well-formedness.

> Fortunatelly this wart is removed by resolution of CWG issue 391.

As are quite a few others ;-)

--
Dave Abrahams
Boost Consulting
www.boost-consulting.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.comeaucomputing.com/csc/faq.html                      ]





Author: James Dennett <jdennett@acm.org>
Date: Sun, 9 Jul 2006 21:47:43 CST
Raw View
Bronek Kozicki wrote:
> James Dennett <jdennett@acm.org> wrote:
>> If a
>> compiler is permitted by the standard to make a copy, and
>> the standard says that doing so would give undefined behavior,
>> then there *is* undefined behavior in that code, as the
>
> No. Standard does not define whether there is UB or not, as it depends
> on how binding rvalues to const reference is implemented by the
> compiler, and standard explicitly grants freedom to compiler vendors to
> make a copy or not. Thus it is *implementation defined* if there is
> undefined behaviour or not.
>
>> standard does not define its result at all.
>
> Indeed

Actually I think I was wrong; trying to determine whether
this is undefined or not is non-trivial, and amounts to
"what do you mean by is".  Is there a copy?  The standard
says that in the abstract machine there may be... but it
is not required.  So if an implementation (say, all of them)
don't make copies, then I agree that you are safe in this
case.

(As others have noted... if a copy is made, all bets are
off, including whether you can detect that copy having
been made.  So it's really vital that the compiler document
whether it will make this copy or not, until the standard
specifies it.)

> but there is slight difference between implementation defined
> behaviour or undefined behaviour.

A huge difference.

> Especially in the light of the fact
> that apparently NO compiler makes that copy and that freedom will be
> taken away in the next release of the standard.

And so we'll never have to discuss this again ;-)

-- James

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: "Tom Widmer" <tom_usenet@hotmail.com>
Date: Mon, 10 Jul 2006 11:59:08 CST
Raw View
Bronek Kozicki wrote:
> Martin Bonner wrote:
> >> The Standard decrees that the code has the potential to invoke undefined
> >> behaviour.
> > No.  It decrees that it DOES invoke undefined behaviour.
>
> no, the code does no invoke undefined behaviour for the same reason for which
> following code compiles successfully on strictest compiler available to me
> (como 4.3.4.1 -A , ie. strict errors).

I think this is an EDG bug.

> class noncopyable
> {
>    noncopyable(const noncopyable&);
> public:
>    noncopyable() {}
> };
>
> class foo : noncopyable
> {};
>
> foo bar() {return foo();}
>
> int main()
> {
>    const foo& f = bar();
> }
>
> .. and the reason is that standard does NOT mandate copy when binding result
> of bar() to f , it just allows it. Only when implementation actually makes
> such a copy, implicit copy constructor of class foo would have been defined,
> thus rendering program ill-formed. If there is a copy or not is implementation
> defined, thus it is also implementation defined if above code is well-formed
> or not, or wheather casting-away const from f would invoke UB or not.

Unfortunately for EDG, the standard states that the definition of bar
is ill-formed, due to 12.2/1 (the potentially elided copy in the return
statement of bar() due to 12.8/15 should not prevent access checking).

Tom

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: Bronek Kozicki <brok@rubikon.pl>
Date: Mon, 10 Jul 2006 15:46:56 CST
Raw View
Tom Widmer wrote:
>> following code compiles successfully on strictest compiler available to me
>> (como 4.3.4.1 -A , ie. strict errors).
>
> I think this is an EDG bug.

I'm pretty certain that it is not a bug and compiler is free not to use copy
constructor ("cctor" for brevity), as explicitly stated in clause 8.5.3
("reference is bound in one of the following ways (the choice is
implementation-defined)"). This choice has nothing to do with cctor elision as
described in clause 12.8/15 ; it is simply not used at all, if vendor choose
so. Also, clause 12.2/1 does not mandate creation of such temporaries; it only
describes program behaviour if they are actually used. Futhermore ...

> Unfortunately for EDG, the standard states that the definition of bar
> is ill-formed, due to 12.2/1 (the potentially elided copy in the return
> statement of bar() due to 12.8/15 should not prevent access checking).

.. access checks have nothing to do with implicit cctor generated by the
compiler, as it is always declared public (see clause 12.8/5 - "An
implicitly-declared copy constructor is an inline public member of its
class.") . It is only its definition, and it only takes place if cctor is
actually used ("An implicitly-declared copy constructor is implicitly defined
if it is used..."), that renders program ill-formed (see exact wording of
clause 12.8/7). Even though it would be defined even if cctor is elided (as
stated therein), clause 8.5.3 explicitly gives implementor choice not to use
cctor *at all*. I cannot see anything that mandates definition of implicit
cctor if it is not used (in the sense of 8.5.3, bullet "The reference is bound
to the object represented by the rvalue..."), nor anything that mandates
access checks to subobjects in such situation.

In this particular situation, implementor made a choice to bind reference to
rvalue directly (as allowed by cited above bullet), the copy constuctor is not
used and not defined, thus program is well-formed.

Is there any specific phrase in the standard (ISO 14882:2003, as in the
current draft copy is simply excluded) that I missed and that would support
your case?


B.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Tue, 11 Jul 2006 15:25:15 GMT
Raw View
brok@rubikon.pl (Bronek Kozicki) writes:

> no, the code does no invoke undefined behaviour for the same reason
> for which following code compiles successfully on strictest compiler
> available to me (como 4.3.4.1 -A , ie. strict errors).

FWIW, whether or not the code invokes undefined behavior is a separate
issue from whether it's well-formed or not.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.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.comeaucomputing.com/csc/faq.html                      ]





Author: brok@rubikon.pl ("Bronek Kozicki")
Date: Thu, 6 Jul 2006 14:32:09 GMT
Raw View
johnchx2@yahoo.com wrote:
>> #include <string>
>> using std::string;
>>
>> string ReturnByValue();    /* Defined elsewhere */
>>
>> int main()
>> {
>>     const string &cr = ReturnByValue();
>>     string &r = const_cast<string&>( cr );
>>     r = "I've been manipulated!";
>> }
>>

> The code above exhibits undefined behavior.  8.5.3/5 indicates that
> the compiler is allowed to introduce a temporary of type const string
> and bind the reference cr to that object.

The above code *would* expose undefined behaviour, had the compiler
actually make such copy. No compiler does that, thus there is no UB.
There is only *potential* risk of thereof, similarly to following:

int main()
{
  int a, b;
  std::cin >> a >> b;
  std::cout << a + b;
}

>     const_cast<int&>( static_cast<const int&>( int() ) ) = 5;
> has undefined behavior under both the current and future rules: the
> reference winds up bound to a temporary of "true" const type, and
> modifying that object results in undefined behavior.

indeed


B.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Thu, 6 Jul 2006 15:23:48 GMT
Raw View
"Bronek Kozicki" posted:


>> The code above exhibits undefined behavior.  8.5.3/5 indicates that
>> the compiler is allowed to introduce a temporary of type const string
>> and bind the reference cr to that object.
>
> The above code *would* expose undefined behaviour, had the compiler
> actually make such copy. No compiler does that, thus there is no UB.


comp.std.c++ is only concerned with fully-portable, Standard-compliant
code.

The Standard decrees that the code has the potential to invoke undefined
behaviour.

Since we only discuss fully-portable code on this newsgroup, and also on
comp.lang.c++, the term "invokes undefined behaviour" may be interpreted
as "is permitted by the Standard to invoke undefined behaviour, and thus
potentially invokes undefined behaviour".

The following doesn't invoke UB on my own computer:

    int i;

    int s = i;


But, in the context of this newsgroup, we state that it does.


--

Frederick Gotham

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Thu, 6 Jul 2006 15:31:34 GMT
Raw View
brok@rubikon.pl ("Bronek Kozicki") writes:

> johnchx2@yahoo.com wrote:
>>> #include <string>
>>> using std::string;
>>>
>>> string ReturnByValue();    /* Defined elsewhere */
>>>
>>> int main()
>>> {
>>>     const string &cr = ReturnByValue();
>>>     string &r = const_cast<string&>( cr );
>>>     r = "I've been manipulated!";
>>> }
>>>
>
>> The code above exhibits undefined behavior.  8.5.3/5 indicates that
>> the compiler is allowed to introduce a temporary of type const string
>> and bind the reference cr to that object.
>
> The above code *would* expose undefined behaviour, had the compiler
> actually make such copy. No compiler does that, thus there is no
> UB.

That logic is flawed.  UB is 100% related to what the standard says
and 100% independent of what any compiler actually does; there's
nothing an implementation can do that changes that (including
documenting the behavior).  If a compiler does not create the copy,
that's simply the way the undefined behavior is expressed on that
implementation.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.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.comeaucomputing.com/csc/faq.html                      ]





Author: johnchx2@yahoo.com
Date: Thu, 6 Jul 2006 10:41:44 CST
Raw View
"Bronek Kozicki" wrote:
> johnchx2@yahoo.com wrote:
> > The code above exhibits undefined behavior.  8.5.3/5 indicates that
> > the compiler is allowed to introduce a temporary of type const string
> > and bind the reference cr to that object.
>
> The above code *would* expose undefined behaviour, had the compiler
> actually make such copy. No compiler does that, thus there is no UB.

I considered this before deciding on the phrasing to use, and came to
the conclusion that the standard doesn't place any restrictions on the
behavior of the code in question, so the code's behavior is in fact
undefined.

I considered whether "don't make a copy and behave as expected or do
make a copy and behave any way you like" could be considered a
"restriction" but I don't believe that it can.  In particular, there is
no way to prove that the compiler has violated it (in the given code
example).

In the case of a class with a copy-ctor with observable effects, you
might be able to extract some kind of guaranteed behavior, but it would
be along the lines of "if the copy-ctor isn't called, the code will
behave as expected; otherwise it may do anything at all, including
calling the copy-ctor."  Not the most useful guarantee.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: brok@rubikon.pl ("Bronek Kozicki")
Date: Fri, 7 Jul 2006 01:20:26 GMT
Raw View
David Abrahams <dave@boost-consulting.com> wrote:
> If a compiler does not create the copy,
> that's simply the way the undefined behavior is expressed on that
> implementation.

I do not understand your logic. UB is *result* of a copy (without copy,
string is non-const, and UB is result of applying const_cast<string&> on
a const string) and not its manifestation. Nothing in the standard
(before that copy happens) suggest that there might be UB (caused by any
something else that a copy).


B.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: usenet-nospam@nmhq.net (Niklas Matthies)
Date: Fri, 7 Jul 2006 01:20:14 GMT
Raw View
On 2006-07-06 16:41, johnchx2@yahoo.com wrote:
:
> In the case of a class with a copy-ctor with observable effects, you
> might be able to extract some kind of guaranteed behavior, but it would
> be along the lines of "if the copy-ctor isn't called, the code will
> behave as expected; otherwise it may do anything at all, including
> calling the copy-ctor."

Don't you mean "...including NOT calling the copy-ctor"?

> Not the most useful guarantee.

-- Niklas Matthies

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: alfps@start.no ("Alf P. Steinbach")
Date: Fri, 30 Jun 2006 16:30:47 GMT
Raw View
* Frederick Gotham:
> "Alf P. Steinbach" posted:
>
>> However, you're posting to the wrong group: questions about possible
>> deficiencies in the language definition (such as, shouldn't we simply
>> get rid of the rvalue concept?) belong in [comp.std.c++].
>>
>> Questions of practical usage belong here, but there's no way the above
>> constitues something anybody (sane, that is) would use.
>
> I disagree, because questions of this nature are so vaguely answered by
> the Standard, the it's pertinent to ask them on the Standard's newsgroup.

I agree.  I'm sorry, I thought I was answering in [comp.lang.c++] and
was directing you here! :-)  Grumble grumble...

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Thu, 29 Jun 2006 04:01:47 GMT
Raw View
I think I have a way of producing a non-const, L-value temporary.

Relevant information:

    (1) A name-less, temporary object is non-const (unless explicitly
defined as const).
    (2) const_cast can be used legitimately to cast away constness from a
pointer or reference in order to alter a non-const object.
    (3) A const reference is an L-value.


And thus I give you:

    int main()
    {
        const_cast<int&>( static_cast<const int&>( int() ) ) = 5;
    }


Three questions:

    (1) Is the program well-formed?
    (2) Does the program invoke undefined behaviour?
    (3) Do I really have a non-const, L-value temporary?


--

Frederick Gotham

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: alfps@start.no ("Alf P. Steinbach")
Date: Thu, 29 Jun 2006 15:04:42 GMT
Raw View
* Frederick Gotham:
> I think I have a way of producing a non-const, L-value temporary.
>
> Relevant information:
>
>     (1) A name-less, temporary object is non-const (unless explicitly
> defined as const).
>     (2) const_cast can be used legitimately to cast away constness from a
> pointer or reference in order to alter a non-const object.
>     (3) A const reference is an L-value.
>
>
> And thus I give you:
>
>     int main()
>     {
>         const_cast<int&>( static_cast<const int&>( int() ) ) = 5;
>     }
>
>
> Three questions:
>
>     (1) Is the program well-formed?
>     (2) Does the program invoke undefined behaviour?
>     (3) Do I really have a non-const, L-value temporary?

I don't know.  The reason this isn't straightforward is that it's
trivial to produce a guaranteed OK non-const temporary lvalue for a
class type object.  Just provide conversion to T&.

However, you're posting to the wrong group: questions about possible
deficiencies in the language definition (such as, shouldn't we simply
get rid of the rvalue concept?) belong in [comp.std.c++].

Questions of practical usage belong here, but there's no way the above
constitues something anybody (sane, that is) would use.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: Frederick Gotham <fgothamNO@SPAM.com>
Date: Thu, 29 Jun 2006 11:17:39 CST
Raw View
"Alf P. Steinbach" posted:


>> Three questions:
>>
>>     (1) Is the program well-formed?
>>     (2) Does the program invoke undefined behaviour?
>>     (3) Do I really have a non-const, L-value temporary?
>
> I don't know.  The reason this isn't straightforward is that it's
> trivial to produce a guaranteed OK non-const temporary lvalue for a
> class type object.  Just provide conversion to T&.


Oh yes, another means I hadn't thought of.


> However, you're posting to the wrong group: questions about possible
> deficiencies in the language definition (such as, shouldn't we simply
> get rid of the rvalue concept?) belong in [comp.std.c++].
>
> Questions of practical usage belong here, but there's no way the above
> constitues something anybody (sane, that is) would use.


I disagree, because questions of this nature are so vaguely answered by
the Standard, the it's pertinent to ask them on the Standard's newsgroup.

Consider the now-years-old question of whether the following is OK:

#include <string>
using std::string;

string ReturnByValue();    /* Defined elsewhere */

int main()
{
    const string &cr = ReturnByValue();

    string &r = const_cast<string&>( cr );

    r = "I've been manipulated!";
}


Code akin to that above has been posted to comp.lang.c++ several times,
but without receiving any definitive answer... thus I say that when the
Standard is too vague about certain things, it's time to come to
comp.std.c++.


--

Frederick Gotham

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: johnchx2@yahoo.com
Date: Thu, 29 Jun 2006 13:02:35 CST
Raw View
Frederick Gotham wrote:

> I disagree, because questions of this nature are so vaguely answered by
> the Standard, the it's pertinent to ask them on the Standard's newsgroup.


Actually, the standard seems pretty clear on the matter (although the
clear answer is, in fact, probably going to change in the next
"release" of the standard).


> Consider the now-years-old question of whether the following is OK:
>
> #include <string>
> using std::string;
>
> string ReturnByValue();    /* Defined elsewhere */
>
> int main()
> {
>     const string &cr = ReturnByValue();
>
>     string &r = const_cast<string&>( cr );
>
>     r = "I've been manipulated!";
> }
>
>
> Code akin to that above has been posted to comp.lang.c++ several times,
> but without receiving any definitive answer... thus I say that when the
> Standard is too vague about certain things, it's time to come to
> comp.std.c++.


The code above exhibits undefined behavior.  8.5.3/5 indicates that the
compiler is allowed to introduce a temporary of type const string and
bind the reference cr to that object.  (The const temporary is
*different from* the non-const temporary returned by the function.)
Modifying a "true" const object results in undefined behavior.

The current working draft of the standard contains an amendment which
would change this for the case where the initializer expression has
class type and is reference-compatible with the type of the reference
(which would apply to the code above):

  http://www2.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#391

The originally posted code, in which the initializer is not of class
type:

     const_cast<int&>( static_cast<const int&>( int() ) ) = 5;

has undefined behavior under both the current and future rules: the
reference winds up bound to a temporary of "true" const type, and
modifying that object results in undefined 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.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Thu, 29 Jun 2006 19:21:57 GMT
Raw View
John posted:

> The originally posted code, in which the initializer is not of class
> type:
>
>      const_cast<int&>( static_cast<const int&>( int() ) ) = 5;
>
> has undefined behavior under both the current and future rules: the
> reference winds up bound to a temporary of "true" const type, and
> modifying that object results in undefined behavior.


You've lost me. At which point in the code snippet do we begin dealing
with a temporary which is const? I'll break the code up into lines:


Line 0:    const int &cr = int();

Line 1:    int &r = const_cast<int&>( cr );

Line 2:    r = 5;


By my current understanding, each line does the following.


Line 0:

    Creates a non-const, R-value, name-less temporary, and binds a const
reference to it (and also extends the temporary's lifetime in the
process).

Line 1:

    Casts away the constness of the const reference, yielding a non-const
L-value. A non-const reference is then bound to this non-const L-value.

At this point, by my current understanding, it appears that "r" is bound
to an object which is non-const (a temporary object albeit, but a non-
const object nonetheless).


Line 2:

    The original name-less temporary object is assigned the value 5.


--

Frederick Gotham

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: johnchx2@yahoo.com
Date: Thu, 29 Jun 2006 15:11:18 CST
Raw View
Frederick Gotham wrote:
> John posted:
>
> > The originally posted code, in which the initializer is not of class
> > type:
> >
> >      const_cast<int&>( static_cast<const int&>( int() ) ) = 5;
> >
> > has undefined behavior under both the current and future rules: the
> > reference winds up bound to a temporary of "true" const type, and
> > modifying that object results in undefined behavior.
>
>
> You've lost me. At which point in the code snippet do we begin dealing
> with a temporary which is const? I'll break the code up into lines:
>
>
> Line 0:    const int &cr = int();
>
> Line 1:    int &r = const_cast<int&>( cr );
>
> Line 2:    r = 5;
>
>
> By my current understanding, each line does the following.
>
>
> Line 0:
>
>     Creates a non-const, R-value, name-less temporary, and binds a const
> reference to it (and also extends the temporary's lifetime in the
> process).

Line 0 is where the tricky stuff happens.

First, it's helpful to keep the terminology straight:  lvalues and
rvalues are expressions, while temporaries are objects (i.e. regions of
storage).  It's useful to distinguish between the objects themselves
and the expressions through which we access the objects.

In line 0, the initializer expression "int()" is an rvalue of type int.
 The final bullet of 8.5.3/5 describes initialization of a reference
from an rvalue of non-class type:

  "...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."

where the reference being initialized is of type cv1 T1&.  In this
case, cv1 = const and T1 = int, so a temporary of type const int is
created, and the reference is bound to *that* temporary.

Since the temporary object to which the reference is bound has const
type, attempting to modify it yields undefined 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.comeaucomputing.com/csc/faq.html                      ]