45

I was wondering what use an rvalue reference member has

class A {
  // ...
  // Is this one useful?
  Foo &&f;
};

Does it have any benefits or drawbacks compared to an lvalue reference member? What is a prime usecase of it?

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • @GMan I don't know why that is better than just saying `template struct acw { T &t; acw(T &&t):t(t) {} template operator U() { return static_cast(std::forward(t)); } }`. What do you gain by having the member `t` an rvalue reference? BTW, I think n3225 says that a defaulted copy constructor is defined as deleted if you have any rvalue reference members. So you still cannot copy a `auto_cast_wrapper` but only move it :) – Johannes Schaub - litb Jan 23 '11 at 20:37
  • Nothing, I just mean I used it lol. And hm, good to know. I'll have to fix it later. – GManNickG Jan 23 '11 at 20:46
  • @GMan Ohh i see now! Thanks for showing, I think it's some interesting tool to use. – Johannes Schaub - litb Jan 23 '11 at 20:54

4 Answers4

29

I've seen one very motivating use case for rvalue reference data members, and it is in the C++0x draft:

template<class... Types>
tuple<Types&&...>
forward_as_tuple(Types&&... t) noexcept;

Effects: Constructs a tuple of references to the arguments in t suitable for forwarding as arguments to a function. Because the result may contain references to temporary variables, a program shall ensure that the return value of this function does not outlive any of its arguments. (e.g., the program should typically not store the result in a named variable).

Returns: tuple<Types&&...>(std::forward<Types>(t)...)

The tuple has rvalue reference data members when rvalues are used as arguments to forward_as_tuple, and otherwise has lvalue reference data members.

I've found forward_as_tuple subsequently helpful when needing to catch variadic arguments, perfectly forward them packed as a tuple, and re-expand them later at the point of forwarding to a functor. I used forward_as_tuple in this style when implementing an enhanced version of tuple_cat proposed in LWG 1385:

http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#1385

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • Could you explain how the rvalue lifetime is managed in this case? Is rvalue destruction is somehow extended until the "later" point when the rvalue is used? – Roman L Jan 23 '11 at 19:55
  • 1
    thanks for your your answer and explanation. The question came up what the requirement "Because the result may contain references to temporary variables, a program shall ensure that the return value of this function does not outlive any of its arguments." implies to a program. Does a snippet like this has undefined behavior? `{ auto x = forward_as_tuple(0); }`, because it violates the shall-requirement in the effects section? Why is such a requirement needed? Is a tuple containing stale references not allowed to be destructed? – Johannes Schaub - litb Jan 23 '11 at 20:08
  • 1
    The client of forward_as_tuple must ensure that the result is "consumed" prior to the sequence point. First examples of its use are found in: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3059.pdf but in this document the function is called pack_arguments instead of forward_as_tuple. The use in N3059 shows the tuple of references being created, passed on to another function, consumed (used), and destructed, in that order. – Howard Hinnant Jan 25 '11 at 15:14
15

According to Stephan T. Lavavej, rvalue reference data members have no use.

[at 31:00] The thing I've seen programmers do when they get hold of rvalue references is that, they start to go a little crazy, because they're so powerful. They start saying "Oh, I'm gonna have rvalue reference data members, I'm gonna have rvalue reference local variables, I'm gonna have rvalue reference return values!" And then they write code like this: [...]

Fabio A.
  • 2,517
  • 26
  • 35
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • Great serie, it's going to take to view that all, but I am looking forward to it :) – Matthieu M. Jan 23 '11 at 15:25
  • 21
    It will be about 10 years before we work out how to use rvalue references correctly. – Martin York Jan 23 '11 at 15:39
  • I guess that programmers are confused about rvalue references and think that they will magically increase the object's lifetime (thus rvalue reference return values), while actually it has nothing to do with the lifetime as explained in the video. – Roman L Jan 23 '11 at 17:27
  • 2
    @7vies: The primary reason programmers are confused about rvalue references is because they are already confused about rvalues. – fredoverflow Jan 23 '11 at 19:21
  • @FredOverflow: Sorry I don't get what you mean. – Roman L Jan 23 '11 at 19:30
  • @7vies: There is nothing *radically* new about rvalue references. My guess is that, compared with other C++0x features, the implementation of rvalue references is trivial. It's just that most C++ programmers don't have a clue what the term "rvalue" really means, which is the single-most hindrance to understanding rvalue references. If you already understand rvalues and references, understanding rvalue references is a matter of minutes. (Mastering the idioms associated with rvalue references will take a little longer, of course. Think chess.) – fredoverflow Jan 23 '11 at 21:33
  • @FredOverflow: Before rvalue references people already knew about const references to temporaries, but there is still confusion when it comes to rvalue references even though they look very like references to temporaries, but non-const ones. I think that it's because of the lifetime issues which are not presented clearly enough when people are talking about rvalue references. – Roman L Jan 23 '11 at 21:46
  • 1
    @Martin: True, and in ten years the C++ Committee will be just about ready to release C++2x which will probably have some completely new type of expression that we'll have to learn... ξvalues, perhaps. – James McNellis Jan 24 '11 at 06:01
  • 4
    @James: I sure hope so. Being stuck with only five different value categories forever would be kinda boring, wouldn't it? – fredoverflow Jan 24 '11 at 10:09
  • 3
    For whom may want to know, he said that at 31:00 in the video. – zwhconst May 09 '19 at 10:17
  • @MartinYork From 10 years later after that comment, I can say it more or less had happen. – Swift - Friday Pie Jul 07 '21 at 07:27
  • @JamesMcNellis aaand they barely dodged that, by writing off concepts and requires-expressions as prvalues – Swift - Friday Pie Jul 07 '21 at 07:36
  • 1
    @Swift-FridayPie Ten years ago what was I doing. Shakes head. – Martin York Jul 07 '21 at 16:04
3

Just thinking out loud here, but wouldn't it have a use in functors? The constructor is often used for "currying", binding some parameters in advance, before the actual function call.

So in this context, the class member is just a staging ground (or a manually implemented closure) for the upcoming function call, and I see no reason why a rvalue reference wouldn't be meaningful there.

But in "regular" non-functor classes, I don't see much point.

jalf
  • 243,077
  • 51
  • 345
  • 550
  • How in this case an rvalue reference is better than a `const &` (or just a normal reference if you need to modify it)? – Roman L Jan 23 '11 at 17:43
  • For the same reason you might otherwise want to pass a rvalue ref to a function: to be able to *move* from it. – jalf Jan 23 '11 at 17:58
  • @jalf: Then just pass by value and move from the parameter to the member. – fredoverflow Jan 23 '11 at 18:46
  • @Fred: presumably the entire point would be to avoid having to pass by value (and perhaps the parameter type isn't copyable, but it may be movable) – jalf Jan 23 '11 at 18:55
  • @jalf: I'm not sure I get your point. Pass by value *means* moving if the argument is an rvalue. [Related FAQ entry](http://stackoverflow.com/questions/3106110/) – fredoverflow Jan 23 '11 at 19:12
  • Isn't this exactly the 'delayed perfect forwarding' mentioned by @sellibitze, who also wasn't sure if it was useful? A curried functor seems like an excellent use for delayed perfect forwarding. Edit: Or would that just open a rvalue_reference_wrapper (cf reference_wrapper) can of worms? – Zero Nov 23 '12 at 07:00
  • Here it is, 10years later, TRUE – Boki Dec 18 '20 at 18:26
3
class A {
  // ...
  // Is this one useful?
  Foo &&f; 
};

In this specific case, there is no reason to use an rvalue reference. It doesn't buy you anything you couldn't have done before.

But you may want to define data members with parameterized types. std::tuple is going to support lvalue and rvalue reference data members, for example. This way it allows you to codify an expression's value category which might come in handy for "delayed perfect forwarding". The standard draft even includes a function template of the form

template<class Args...>
tuple<Args&&...> pack_arguments(Args&&...args);

But I'm honestly not sure about its usefulness.

sellibitze
  • 27,611
  • 3
  • 75
  • 95
  • 1
    This post explains one possible use of forward_as_tuple or pack_arguments: http://cpptruths.blogspot.com/2012/06/perfect-forwarding-of-parameter-groups.html – Sumant Jun 11 '12 at 00:25