Topic: std::move and lvalues (was: Catch by rvalue reference)


Author: Scott Meyers <usenet@aristeia.com>
Date: Tue, 26 May 2009 11:43:38 CST
Raw View
doug.gregor@gmail.com wrote:
> I believe it was originally an oversight. However, this issue was
> discussed at the most recent C++ committee meeting, as part of the
> discussion of N2831, a change that prevents rvalue references from
> binding to lvalues.
[...]
> decided to make rvalue-reference handlers ill-formed. The change is
> part of N2844 (the successor to N2831), which was voted into the
> working paper and will appear in the post-Summit mailing.

N2844 proposes that std::move be declared as follows,

    template <RvalueOf T> RvalueOf<T>::type move(T&& t);

and that's how it appears in both CD1 (N2800) and the current draft (N2857).  I
must be missing something really basic, because move's parameter here is an
rvalue reference, and if lvalues no longer bind to rvalue references, how can an
lvalue be turned into an rvalue via move?

Thanks,

Scott

--
[ 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: Tue, 26 May 2009 16:46:53 CST
Raw View
On 26 Mai, 19:43, Scott Meyers <use...@aristeia.com> wrote:
> doug.gre...@gmail.com wrote:
> > I believe it was originally an oversight. However, this issue was
> > discussed at the most recent C++ committee meeting, as part of the
> > discussion of N2831, a change that prevents rvalue references from
> > binding to lvalues.
> [...]
> > decided to make rvalue-reference handlers ill-formed. The change is
> > part of N2844 (the successor to N2831), which was voted into the
> > working paper and will appear in the post-Summit mailing.
>
> N2844 proposes that std::move be declared as follows,
>
>     template <RvalueOf T> RvalueOf<T>::type move(T&& t);
>
> and that's how it appears in both CD1 (N2800) and the current draft (N2857).  I
> must be missing something really basic, because move's parameter here is an
> rvalue reference, and if lvalues no longer bind to rvalue references, how can an
> lvalue be turned into an rvalue via move?

Note that the *exact* function parameter T&& where T is a template
parameter of a function template is specially ruled. According to
[temp.deduct.call]/3:

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

So, it depends on the lvalue-ness of the argument, whether the
result will actually bind to an lvalue reference or an rvalue
reference depending on the result of the potentially occurring
reference collapsing ([temp.arg.type]/4). Above wording ensures
that deduction rules apply after this transformation. This
behavior is essential to realize the so-called perfect forwarding
behavior.

Greetings from Bremen,

Daniel


--
[ 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: Tue, 26 May 2009 16:48:48 CST
Raw View
On 26 Mai, 19:43, Scott Meyers <use...@aristeia.com> wrote:
> N2844 proposes that std::move be declared as follows,
>
>     template <RvalueOf T> RvalueOf<T>::type move(T&& t);
>
> and that's how it appears in both CD1 (N2800) and the current draft (N2857).  I
> must be missing something really basic, because move's parameter here is an
> rvalue reference, and if lvalues no longer bind to rvalue references, how can an
> lvalue be turned into an rvalue via move?

There's a special type deduction rule for rvalue value references that
also involves reference collapsing:

   template<typename T>
   void foo(T&& x) {}

   void bar() {
     foo(23); // T = int, T&& = int&
     int lv = 23;
     foo(lv); // T = int&, T&& = int&
   }

Perfect forwarding relies on this.

However, the current draft is still buggy with respect to the
definition of the RvalueOf concept. Lvalue references actually can't
satisfy this concept -- not even with the proposed concept_map. (See
my post on rvalue reference / concept issues)

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: SG <s.gesemann@gmail.com>
Date: Wed, 27 May 2009 10:55:02 CST
Raw View
On 27 Mai, 00:48, SG <s.gesem...@gmail.com> wrote:
> On 26 Mai, 19:43, Scott Meyers <use...@aristeia.com> wrote:
>    template<typename T>
>    void foo(T&& x) {}
>
>    void bar() {
>      foo(23); // T = int, T&& = int&
>      int lv = 23;
>      foo(lv); // T = int&, T&& = int&
>    }

The first comment contains a typo. It should have been
   1.  T = int,  T&& = int&&
   2.  T = int&, T&& = int&

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                      ]