Topic: c++0x rvalue references safety problem.


Author: daniel.kruegler@googlemail.com
Date: Mon, 11 May 2009 01:10:50 CST
Raw View
On 10 Mai, 23:24, german diago <germandi...@gmail.com> wrote:
> > "If P is a reference type, the type referred to by P is used for
> > type deduction. If P is of the form T&&, where T is a template
> > parameter, and the argument is an lvalue, the type A& is used
> > in place of A for type deduction.
>
> I think this solves the problem. But the problem now is that rvalue
> references
> cannot bind to lvalues EXCEPT in this case. This is an exception to
> the rule, and I think this is confusing.

It is not true, that this rule makes an rvalue reference bind to
an lvalue reference. The point is that T&& just *looks* like
an rvalue reference. At the point of the function declaration
it cannot be decided yet, what it actually will be. *If* an
lvalue is provided as argument, the compiler is supposed to
use A& as the actual argument. This has the effect, that
T&& becomes a A&&& and now reference-collapsing happens
([temp.arg.type]/4) which ends in an A&, which is an lvalue
reference and now the lvalue correctly bind to the lvalue.

This is no exception from the binding rule.

> Why do they do that, when they can do
> what I
> proposed and make everything uniform without exceptions? I mean you
> can do this:
>
> template <typename Arg1, typename... Args>
> void func(Arg1 arg, Args... rest);
>
> func(ref(arg1), move(arg2)...);

What is the advantage of this? Users cannot see from
the function declaration what they are supposed to
provide, so why should they worry about? The disadvantage
of above declaration is that it's quite easy to perform
unintended type-slicing, when they forget about the ref()
wrapper and a static base class is provided with a dynamic
type different from that.

Note that a perfect forwarding function has just one
responsibility and that is to just forward all arguments
as they currently are. This doesn't work with your
function template above.

Greetings from Bremen,

Daniel Kr   gler


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: SG <s.gesemann@gmail.com>
Date: Mon, 11 May 2009 13:19:53 CST
Raw View
On 10 Mai, 23:24, german diago <germandi...@gmail.com> wrote:
> > "If P is a reference type, the type referred to by P is used for
> > type deduction. If P is of the form T&&, where T is a template
> > parameter, and the argument is an lvalue, the type A& is used
> > in place of A for type deduction.
>
> I think this solves the problem. But the problem now is that rvalue
> references
> cannot bind to lvalues EXCEPT in this case. This is an exception to
> the rule,

Even in this case they can't! T&& *is* an lvalue reference if T is an
lvalue reference (reference collapsing). If T is to be deduced it'll
be deduced to be an lvalue reference in case the argument was an
lvalue expression (template argument deduction rules).

> and I think this is confusing. Why do they do that, when they can do
> what I
> proposed and make everything uniform without exceptions? I mean you
> can do this:
>
> template <typename Arg1, typename... Args>
> void func(Arg1 arg, Args... rest);
>
> func(ref(arg1), move(arg2)...);

What problem is this going to solve?! You have to explain it a little
more. What are you trying to do? How's what you're trying to do not
possible with the current rules and how is your proposal any better?

Cheers!
SG

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: german diago <germandiago@gmail.com>
Date: Sat, 9 May 2009 11:22:40 CST
Raw View
Hello. I've seen there is a change proposed in rvalue references to
fix a safety problem.

The resolution is that rvalue references cannot bind to any lvalue
anymore.

I wonder if this brings this problem:

template <typename Arg1, typename...Args>
void func(Arg1 && arg1, Args &&... rest);

Now, this cannot be done anymore, we need to overload every
combination of rvalue and lvalue references. Am I correct? Anyway, I
think this is possible too now:


template <typename Arg1, typenam... Args>
void func(Arg1 arg1, Args... args); ...


ffunc(std::move(arg1), std::ref(arg2)...);

Am I correct? Thanks in advance.


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: daniel.kruegler@googlemail.com
Date: Sat, 9 May 2009 23:23:09 CST
Raw View
On 9 Mai, 19:22, german diago <germandi...@gmail.com> wrote:
> Hello. I've seen there is a change proposed in rvalue references to
> fix a safety problem.

This is correct.

> The resolution is that rvalue references cannot bind to any lvalue
> anymore.

Also true (in general).

> I wonder if this brings this problem:
>
> template <typename Arg1, typename...Args>
> void func(Arg1 && arg1, Args &&... rest);
>
> Now, this cannot be done anymore, we need to overload every
> combination of rvalue and lvalue references. Am I correct?

Fortunately you are not ;-) Note that in above case Arg1 and
follow-up's are direct template parameters. Now
[temp.deduct.call]/3 comes into the game:

"If P is a reference type, the type referred to by P is used for
type deduction. If P is of the form T&&, where T is a template
parameter, and the argument is an lvalue, the type A& is used
in place of A for type deduction.

This solves the so-called perfect-forwarding problem and above
func() copes perfectly with rvalues and lvalues.

> Anyway, I
> think this is possible too now:
>
> template <typename Arg1, typenam... Args>
> void func(Arg1 arg1, Args... args); ...
>
> ffunc(std::move(arg1), std::ref(arg2)...);
>
> Am I correct? Thanks in advance.

You can do that but it is not necessary.

HTH & Greetings from Bremen,

Daniel Kr   gler


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: SG <s.gesemann@gmail.com>
Date: Sun, 10 May 2009 15:23:03 CST
Raw View
On 9 Mai, 19:22, german diago <germandi...@gmail.com> wrote:
> Hello. I've seen there is a change proposed in rvalue references to
> fix a safety problem.
> The resolution is that rvalue references cannot bind to any lvalue
> anymore.

Yes.

> I wonder if this brings this problem:
>
> template <typename Arg1, typename...Args>
> void func(Arg1 && arg1, Args &&... rest);
>
> Now, this cannot be done anymore, we need to overload every
> combination of rvalue and lvalue references. Am I correct?

I'm not sure what you mean by "this". The new rvalue reference rules
havn't changed template argument deduction and reference collapsing.
So, func still accepts lvalues and rvalues. Example:

 int i = 23;
 func(i,i+3); // OK, func<int&,int>(int&,int&&)

> Anyway, I think this is possible too now:
>
> template <typename Arg1, typenam... Args>
> void func(Arg1 arg1, Args... args); ...
>
> ffunc(std::move(arg1), std::ref(arg2)...);
>
> Am I correct? Thanks in advance.

It's not clear what you're trying to "solve".

Cheers!
SG

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: german diago <germandiago@gmail.com>
Date: Sun, 10 May 2009 15:24:04 CST
Raw View
> "If P is a reference type, the type referred to by P is used for
> type deduction. If P is of the form T&&, where T is a template
> parameter, and the argument is an lvalue, the type A& is used
> in place of A for type deduction.

I think this solves the problem. But the problem now is that rvalue
references
cannot bind to lvalues EXCEPT in this case. This is an exception to
the rule,
and I think this is confusing. Why do they do that, when they can do
what I
proposed and make everything uniform without exceptions? I mean you
can do this:

template <typename Arg1, typename... Args>
void func(Arg1 arg, Args... rest);



func(ref(arg1), move(arg2)...);


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]