What are they useful for?

http://en.cppreference.com/w/cpp/language/member_functions
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
struct S {
    void f() & { std::cout << "lvalue\n"; }
    void f() &&{ std::cout << "rvalue\n"; }
};
 
int main(){
    S s;
    s.f();            // prints "lvalue"
    std::move(s).f(); // prints "rvalue"
    S().f();          // prints "rvalue"
}
This is a cool feature I didn't know about, and I am curious of some practical/effective uses for it.
Isn't the reason for them explained in the paragraph immediately following prior to that code? You want the function to do one thing in the event that it is being called from\as an lvalue and something completely different for an rvalue.
Last edited on
It's an optimization thing. If a function is potentially destructive to the object's state, you can overload the same function in 2 ways:

lvalue function: Will do the extra work to preserve the object's state

rvalue function: Can be faster and let the object's state fall to pieces, because it's a temp object anyway.


EDIT:

You want the function to do one thing in the event that it is being called from\as an lvalue and something completely different for an rvalue.


In general... that would be pretty horrible if your code actually did that. People would expect both versions of the function to behave the same (at least from a viewpoint external to the class).
Last edited on
Some people also like to lvalue ref qualify their copy-assignments and other operators that require lvalues in their built-in versions, to avoid the sort of silly code like std::string() = "abc"; that we put up with in C++98.

but yes, the real point is to trash this if you're the rvalue overload.
Thanks, so it's a way to manually optimize the program :)
> so it's a way to manually optimize the program

It could be used for manual optimization.
But its primary purpose, and most common use, is to allow class authors to enforce correct semantics.

This is the kind of code that people tend to routinely write
(return an expensive-to-copy object by reference to const):
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <string>
#include <vector>

struct A
{
    const std::vector<std::string>& names() const { return names_ ; }

    std::vector<std::string> names_ ;
};

And it could be disastrous if A::names() is naively or carelessly called on an rvalue:
1
2
3
4
5
6
7
A foo() { return { { "one", "two", "three", "four", "five", "six" } } ; }

int main()
{
    for( const auto& s : foo().names() ) std::cout << s << ' ' ; // UB
    std::cout << '\n' ;
}

http://coliru.stacked-crooked.com/a/e5185f51151de5ed


With an overload for rvalues, the class author can enforce correct semantics.
(either return a copy by value, or disable the function altogether for rvalues):
http://coliru.stacked-crooked.com/a/6558e48bbabbecf1
Topic archived. No new replies allowed.