Topic: (N2118)Rvalue reference may create a loophole in the type system
Author: pongba@gmail.com
Date: Wed, 18 Jul 2007 22:44:05 CST Raw View
In particular I'm considering the following code:
int&& i = 0;
i++;
this actually compiles(because a named rvalue reference is treated as
a lvalue for safety reasons(e.g. moved more than once)), which is very
bothersome, because the whole point of the current wording that
forbids non-const reference to bind to rvalue is to prevent users from
modifying a rvalue through a reference.
Now this safe-net is broken.
IMO the wording(N2118) should be strengthened, so that for build
operators, rvalue references are treated as rvalue, thus preventing i+
+ from compiling.
---
[ 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@spam-trap-cop.net>
Date: Thu, 19 Jul 2007 08:25:35 CST Raw View
pongba@gmail.com wrote:
> In particular I'm considering the following code:
>
> int&& i = 0;
> i++;
>
> this actually compiles(because a named rvalue reference is treated as
> a lvalue for safety reasons(e.g. moved more than once)), which is very
> bothersome,
or is it not? You just incremented a *temporary* created from a literal,
and this temporary value is not const (and lives long enough to be
safely accessed in the second line). Also, you used rvalue-reference and
not plain reference, thus the intent is quite visible in the code.
Anything wrong with it?
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: Thu, 19 Jul 2007 15:24:50 GMT Raw View
on Thu Jul 19 2007, pongba-AT-gmail.com wrote:
> In particular I'm considering the following code:
>
> int&& i = 0;
> i++;
>
> this actually compiles(because a named rvalue reference is treated as
> a lvalue for safety reasons(e.g. moved more than once)), which is very
> bothersome, because the whole point of the current wording that
> forbids non-const reference to bind to rvalue is to prevent users from
> modifying a rvalue through a reference.
rvalue references provide a way to _explicitly_ circumvent that rule.
That's a major feature, without which rvalue references would be
useless.
One might consider prohibiting auto ("on the stack") rvalue
references, though. I'm not sure whether they're useful. Howard?
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
The Astoria Seminar ==> http://www.astoriaseminar.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: Thorsten Ottosen <thorsten.ottosen@dezide.com>
Date: Thu, 19 Jul 2007 14:56:20 CST Raw View
David Abrahams skrev:
> on Thu Jul 19 2007, pongba-AT-gmail.com wrote:
>
>> In particular I'm considering the following code:
>>
>> int&& i = 0;
>> i++;
>>
>> this actually compiles
Why is that surprising? Do you also find
vector<int> get_vector();
vector<int>&& v = get_vector();
surprising?
> rvalue references provide a way to _explicitly_ circumvent that rule.
> That's a major feature, without which rvalue references would be
> useless.
>
> One might consider prohibiting auto ("on the stack") rvalue
> references, though. I'm not sure whether they're useful. Howard?
It would be bad to prohibit that IMO. For example, the new for-loop uses it:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2243.html#the-range-based-for-statement
-Thorsten
---
[ 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: pongba@gmail.com
Date: Fri, 20 Jul 2007 01:59:27 CST Raw View
On Jul 20, 4:56 am, Thorsten Ottosen <thorsten.otto...@dezide.com>
wrote:
> David Abrahams skrev:
>
> > on Thu Jul 19 2007, pongba-AT-gmail.com wrote:
>
> >> In particular I'm considering the following code:
>
> >> int&& i = 0;
> >> i++;
>
> >> this actually compiles
>
> Why is that surprising? Do you also find
>
> vector<int> get_vector();
> vector<int>&& v = get_vector();
>
> surprising?
>
> > rvalue references provide a way to _explicitly_ circumvent that rule.
> > That's a major feature, without which rvalue references would be
> > useless.
>
> > One might consider prohibiting auto ("on the stack") rvalue
> > references, though. I'm not sure whether they're useful. Howard?
Aren't they on the stack anyway? I mean, even when I'm writing a move
constructor, the rvalue reference parameter is on the stack.
> It would be bad to prohibit that IMO. For example, the new for-loop uses it:
>
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2243.html#th...
>
Good Point!
---
[ 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: pongba@gmail.com
Date: Fri, 20 Jul 2007 08:21:24 CST Raw View
On Jul 19, 11:24 pm, d...@boost-consulting.com (David Abrahams) wrote:
> on Thu Jul 19 2007, pongba-AT-gmail.com wrote:
>
> > In particular I'm considering the following code:
>
> > int&& i = 0;
> > i++;
>
> > this actually compiles(because a named rvalue reference is treated as
> > a lvalue for safety reasons(e.g. moved more than once)), which is very
> > bothersome, because the whole point of the current wording that
> > forbids non-const reference to bind to rvalue is to prevent users from
> > modifying a rvalue through a reference.
>
> rvalue references provide a way to _explicitly_ circumvent that rule.
> That's a major feature, without which rvalue references would be
> useless.
How about:
double d = 0;
int&& r = d;
r++; // a *temporary* is incremented, which has nothing to do with d
Isn't this surprising? I mean, given that the current rule prevent
this from happening through only allowing a const reference to bind to
a rvalue.
---
[ 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, 20 Jul 2007 15:47:06 GMT Raw View
on Fri Jul 20 2007, pongba-AT-gmail.com wrote:
>
> How about:
>
> double d = 0;
> int&& r = d;
> r++; // a *temporary* is incremented, which has nothing to do with d
Huh?
> Isn't this surprising?
Your comment is surprising. What makes you think a temporary is
incremented, and d isn't incremented, here?
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
The Astoria Seminar ==> http://www.astoriaseminar.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: dave@boost-consulting.com (David Abrahams)
Date: Fri, 20 Jul 2007 15:47:45 GMT Raw View
on Fri Jul 20 2007, pongba-AT-gmail.com wrote:
>> > rvalue references provide a way to _explicitly_ circumvent that rule.
>> > That's a major feature, without which rvalue references would be
>> > useless.
>>
>> > One might consider prohibiting auto ("on the stack") rvalue
>> > references, though. I'm not sure whether they're useful. Howard?
>
> Aren't they on the stack anyway? I mean, even when I'm writing a move
> constructor, the rvalue reference parameter is on the stack.
That's why I put it in quotes. I meant only to include rvalue
references that are (implicitly) declared auto (the old meaning of
auto).
And, FWIW, I didn't mean to include rvalue references that use the new
meaning of auto.
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
The Astoria Seminar ==> http://www.astoriaseminar.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: jam <farid.mehrabi@gmail.com>
Date: Fri, 20 Jul 2007 11:08:53 CST Raw View
On Jul 20, 5:21 pm, pon...@gmail.com wrote:
> On Jul 19, 11:24 pm, d...@boost-consulting.com (David Abrahams) wrote:
>
>
>
>
>
> > on Thu Jul 19 2007, pongba-AT-gmail.com wrote:
>
> > > In particular I'm considering the following code:
>
> > > int&& i = 0;
> > > i++;
>
> > > this actually compiles(because a named rvalue reference is treated as
> > > a lvalue for safety reasons(e.g. moved more than once)), which is very
> > > bothersome, because the whole point of the current wording that
> > > forbids non-const reference to bind to rvalue is to prevent users from
> > > modifying a rvalue through a reference.
>
> > rvalue references provide a way to _explicitly_ circumvent that rule.
> > That's a major feature, without which rvalue references would be
> > useless.
>
> How about:
>
> double d = 0;
> int&& r = d;
> r++; // a *temporary* is incremented, which has nothing to do with d
>
> Isn't this surprising? I mean, given that the current rule prevent
> this from happening through only allowing a const reference to bind to
> a rvalue.
>
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-...@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ:http://www.comeaucomputing.com/csc/faq.html ]- Hide quoted text -
>
> - Show quoted text -
In order to prevent this ,could built-in casting operators for
intrinsic types be interpreted as const operators (e.g operator const
int(const double&) )??
regards,
FM.
---
[ 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: pongba@gmail.com
Date: Sat, 21 Jul 2007 00:45:12 CST Raw View
On Jul 20, 11:47 pm, d...@boost-consulting.com (David Abrahams) wrote:
> on Fri Jul 20 2007, pongba-AT-gmail.com wrote:
>
>
>
> > How about:
>
> > double d = 0;
> > int&& r = d;
> > r++; // a *temporary* is incremented, which has nothing to do with d
>
> Huh?
>
> > Isn't this surprising?
>
> Your comment is surprising. What makes you think a temporary is
> incremented, and d isn't incremented, here?
Well, the output of my code under the conceptgcc-boostcon edition is
my first clue.
Second, since d isn't reference-compatible with r, r is supposed to be
bound to a temporary created by copy initialization from d, according
to N2118:
8.5.3
Otherwise, a temporary of type ``cv1 T1" is created and initialized
from the initializer expression using the rules for a non-reference
copy initialization (dcl.init). The reference is then bound to the
temporary.
---
[ 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: Mathias Gaunard <loufoque@gmail.com>
Date: Sat, 21 Jul 2007 04:53:52 CST Raw View
On Jul 20, 5:47 pm, d...@boost-consulting.com (David Abrahams) wrote:
> > double d = 0;
> > int&& r = d;
> > r++; // a *temporary* is incremented, which has nothing to do with d
> Your comment is surprising. What makes you think a temporary is
> incremented, and d isn't incremented, here?
Because double isn't int.
The double is converted to an int, hence introducing a temporary.
---
[ 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: David Abrahams <dave@boost-consulting.com>
Date: Sun, 22 Jul 2007 13:16:39 CST Raw View
on Sat Jul 21 2007, Mathias Gaunard <loufoque-AT-gmail.com> wrote:
> On Jul 20, 5:47 pm, d...@boost-consulting.com (David Abrahams) wrote:
>
>> > double d = 0;
>> > int&& r = d;
>> > r++; // a *temporary* is incremented, which has nothing to do with d
>
>> Your comment is surprising. What makes you think a temporary is
>> incremented, and d isn't incremented, here?
>
> Because double isn't int.
Ohhhh... I missed that part, which I guess is the whole point.
> The double is converted to an int, hence introducing a temporary.
Right.
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
The Astoria Seminar ==> http://www.astoriaseminar.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: "Bronek Kozicki" <brok@spam-trap-cop.net>
Date: Sun, 22 Jul 2007 13:16:08 CST Raw View
jam <farid.mehrabi@gmail.com> wrote:
> In order to prevent this ,could built-in casting operators for
> intrinsic types be interpreted as const operators (e.g operator const
> int(const double&) )??
and what would that limitation buy us? I find it quite natural that
temporary copy can be operated upon independly of its source value.
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: fishcorn@gmail.com (John Moeller)
Date: Sun, 22 Jul 2007 18:16:03 GMT Raw View
pongba@gmail.com wrote:
> On Jul 20, 11:47 pm, d...@boost-consulting.com (David Abrahams) wrote:
>> on Fri Jul 20 2007, pongba-AT-gmail.com wrote:
>>
>>
>>
>>> How about:
>>> double d = 0;
>>> int&& r = d;
>>> r++; // a *temporary* is incremented, which has nothing to do with d
>> Huh?
>>
>>> Isn't this surprising?
>> Your comment is surprising. What makes you think a temporary is
>> incremented, and d isn't incremented, here?
>
> Well, the output of my code under the conceptgcc-boostcon edition is
> my first clue.
>
> Second, since d isn't reference-compatible with r, r is supposed to be
> bound to a temporary created by copy initialization from d, according
> to N2118:
>
> 8.5.3
> Otherwise, a temporary of type ``cv1 T1" is created and initialized
> from the initializer expression using the rules for a non-reference
> copy initialization (dcl.init). The reference is then bound to the
> temporary.
Regardless, I can't say that I'm surprised by your code. You're
grabbing a non-const rvalue (because you assigned it to a non-const
rvalue reference), and you're performing a non-const operation on it.
In the code, you're stating exactly what you want to do (convert a
double to an int and increment the result), and it does it. I don't
really understand where the surprise is. What if you were to do this:
double d = 0.0;
int r = d;
r++;
Would you be surprised at the result?
Can you explain where the concern about type-safety is? Maybe we need
an example with classes instead of primitives?
--
John Moeller
fishcorn@gmail.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: jam <farid.mehrabi@gmail.com>
Date: Wed, 25 Jul 2007 09:52:28 CST Raw View
On Jul 22, 10:16 pm, "Bronek Kozicki" <b...@spam-trap-cop.net> wrote:
> jam <farid.mehr...@gmail.com> wrote:
> > In order to prevent this ,could built-in casting operators for
> > intrinsic types be interpreted as const operators (e.g operator const
> > int(const double&) )??
I felt great regret after that post of mine(this happens often).
> and what would that limitation buy us? I find it quite natural that
> temporary copy can be operated upon independly of its source value.
right.
regards,
FM
---
[ 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: jcoffin@taeus.com (Jerry Coffin)
Date: Wed, 25 Jul 2007 23:10:16 GMT Raw View
In article <1184911584.328516.62110@g12g2000prg.googlegroups.com>,
pongba@gmail.com says...
[ ... ]
> How about:
>
> double d = 0;
> int&& r = d;
> r++; // a *temporary* is incremented, which has nothing to do with d
>
> Isn't this surprising? I mean, given that the current rule prevent
> this from happening through only allowing a const reference to bind to
> a rvalue.
If you really want 'r' to be an rvalue reference to the same type as
'd', shouldn't you really use auto (in its new meaning) to express that
intent directly?
--
Later,
Jerry.
The universe is a figment of its own imagination.
---
[ 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: frege <gottlobfrege@gmail.com>
Date: Thu, 26 Jul 2007 00:00:29 CST Raw View
On Jul 25, 7:10 pm, jcof...@taeus.com (Jerry Coffin) wrote:
>
> If you really want 'r' to be an rvalue reference to the same type as
> 'd', shouldn't you really use auto (in its new meaning) to express that
> intent directly?
>
Speaking of auto and rvalue refs, I've been meaning to ask (to Howard
mostly, based on a slide from the BoostCon)...
void f(int i)
{
}
void f(int const & cr)
{
}
void f(int && r)
{
auto q = r;
decltype(r) s = r;
f(r);
f(q);
f(s);
f(std::move(r));
//etc
}
what are the types of q and s? which f is called in each case?
what about
template <typename T>
void f(T t)
{
auto q = t;
decltype(t) s = t;
//...
}
for most types T, I suspect q and s are of type T, but I'm not so sure
when T is a &&.
so are these 3 functions different:
template <typename T>
void f1(T t)
{
f(t);
}
template <typename T>
void f2(T t)
{
auto q = t;
f(q);
}
template <typename T>
void f2(T t)
{
decltype(t) q = t;
f(q);
}
I'd like to think that the creation of a temporary doesn't (typically
- ie for regular types) change anything, but does it when T is an
rvalue ref?
Tony
---
[ 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: howard.hinnant@gmail.com (Howard Hinnant)
Date: Thu, 26 Jul 2007 21:02:59 GMT Raw View
In article <1185425242.169428.219920@i38g2000prf.googlegroups.com>,
frege <gottlobfrege@gmail.com> wrote:
> On Jul 25, 7:10 pm, jcof...@taeus.com (Jerry Coffin) wrote:
> >
> > If you really want 'r' to be an rvalue reference to the same type as
> > 'd', shouldn't you really use auto (in its new meaning) to express that
> > intent directly?
> >
>
>
> Speaking of auto and rvalue refs, I've been meaning to ask (to Howard
> mostly, based on a slide from the BoostCon)...
>
> void f(int i)
> {
> }
> void f(int const & cr)
> {
> }
> void f(int && r)
> {
> auto q = r;
> decltype(r) s = r;
> f(r);
> f(q);
> f(s);
> f(std::move(r));
> //etc
> }
>
> what are the types of q and s? which f is called in each case?
Partial answer:
f(int) and f(int const &) are ambiguous (under C++03 and C++0X).
I don't know what auto does (haven't kept up with it, and I don't
believe it is in the draft yet).
Otherwise, every use of r, q, and s inside of f() will be treated as an
lvalue, not as an rvalue. There's only two places where named variables
will be treated as rvalues: both of those places are where copy elision
is already legal today.
1. Returning a local auto-storage variable by value.
2. Throwing a local auto-storage variable.
> what about
>
> template <typename T>
> void f(T t)
> {
> auto q = t;
> decltype(t) s = t;
> //...
> }
>
> for most types T, I suspect q and s are of type T, but I'm not so sure
> when T is a &&.
By today's rules, if you:
void g()
{
int i = 0;
int& ir = i;
f(ir);
}
T is deduced as int, not int&. Same answer if you change ir:
int&& ir = i;
Summary: There are only a few places where && behaves differently from
&. If in doubt, assume that && behaves the same as &, and you'll be
correct more often than not.
>
> so are these 3 functions different:
>
> template <typename T>
> void f1(T t)
> {
> f(t);
> }
>
> template <typename T>
> void f2(T t)
> {
> auto q = t;
> f(q);
> }
>
> template <typename T>
> void f2(T t)
> {
> decltype(t) q = t;
> f(q);
> }
>
> I'd like to think that the creation of a temporary doesn't (typically
> - ie for regular types) change anything, but does it when T is an
> rvalue ref?
All of those should behave identically, treating t and q as lvalues.
If you have a name for it (a variable name), it is an lvalue. It will
prefer lvalue references in overload resolution.
If you don't have a name for it (such as the return value of a
function), then it is an rvalue ... with one exception: unnamed lvalue
references are lvalues.
A& an_lvalue();
A&& an_rvalue();
A another_rvalue();
char source(const A&);
int source(A&&);
int main()
{
A a;
an_lvalue() = a; // ok
an_rvalue() = a; // compile time error
another_rvalue() = a; // compile time error
A&& ar = a; // ar is an lvalue, it has a name "ar"
ar = a; // ok
char c1 = source(ar); // returns char, not int
char c2 = source(an_lvalue()); // returns char
int i1 = source(an_rvalue()); // returns int
}
-Howard
---
[ 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 ]