this by rvalue

J

Jan Bielawski

I was reading up on the new C++0x features and have a question:

Is there a way to overload on the rvalue-ness of the invoking object
itself? In other words, distinguish between:

// contrived example
X x;
x.foo();

and:

X f();
f().foo();

A less contrived example would be a member X::eek:perator+() which would
distinguish between the first and the second invocation in the line
below:

X x, y, z;
X xx = x + y + z

So the first + sign would resolve to <lvalue>.operator+(y), and the
second + sign would resolve to <rvalue>.operator+(z)
(where the second one is presumably moving instead of copying).

Is this available? Is it at all useful? It's as if there was a "&&"
qualifier (or whatever it's called) analogous to "const" in method
declaration:

X X::eek:perator+(const X& rhs) {...} // as usual
X X::eek:perator+(const X& rhs) && {...} // the one invoked on
rvalue
X X::eek:perator+(const X& rhs) const {...} // the one invoked on
const

Does this even make any sense?
 
S

SG

I was reading up on the new C++0x features and have a question:

Is there a way to overload on the rvalue-ness of the invoking object
itself? In other words, distinguish between:

    // contrived example
    X x;
    x.foo();

and:

    X f();
    f().foo();

Yes. That's where "ref qualifiers" come in:

class X {
public:
void foo() &;
void foo() &&;
};
A less contrived example would be a member X::eek:perator+() which would
distinguish between the first and the second invocation in the line
below:

    X x, y, z;
    X xx = x + y + z

So the first + sign would resolve to <lvalue>.operator+(y), and the
second + sign would resolve to <rvalue>.operator+(z)
(where the second one is presumably moving instead of copying).

Possible but unusable. I would write a free operator+ in terms of +=:

class X {
public:
...
X& operator=(X const&) &;
X& operator=(X &&) &;

X& operator+=(X const&) &;
X& operator+=(X &&) &;
...
};

inline X operator+(X const& lhs, X const& rhs) {
X temp = lhs;
temp += rhs;
return temp;
}

inline X operator+(X && lhs, X const& rhs) {
return std::move(lhs += rhs);
}
Is this available? Is it at all useful? It's as if there was a "&&"
qualifier (or whatever it's called) analogous to "const" in method
declaration:

    X X::eek:perator+(const X& rhs) {...}  // as usual
    X X::eek:perator+(const X& rhs) && {...}  // invoked on rvalue
    X X::eek:perator+(const X& rhs) const {...}  // invoked on const

Almost. You can't overload the functions like this. You can't have two
member function which only differ in one lacking a ref qualifier and
the other one having some ref qualifier. To make this work you need to
add an lvalue ref qualifier ("&") for the first function. But what
would be the difference between the first and the third function? I
hope none. You should at least remove the first function.

Cheers!
SG
 
N

Niels Dekker - no reply address

Yes. That's where "ref qualifiers" come in:

class X {
public:
void foo() &;
void foo() &&;
};

Good question. Is there any compiler already supporting ref qualifiers for
member functions?

I do think so, yes. Have a look at the examples from a paper by Daveed
Vandevoorde and Bronek Kozicki, Extending Move Semantics To *this,
www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1821.htm

The first example shows how an lvalue ref qualifier can be used to avoid
accidentally taking the address of an rvalue, or assigning to an rvalue:

struct S {
S* operator &() &;
S& operator=(S const&) &;
};

The second example shows how an rvalue ref qualifier allows move semantics
for the data of an rvalue object:

class X {
std::vector<char> data_;
public:
// ...
std::vector<char> const & data() const & { return data_; }
std::vector<char> && data() && { return data_; }
};

(Both examples are from the paper.)

Actually I did a proposal to add lvalue ref qualifiers to assignment
operators in the Standard Library. Written together with Daniel Kruegler:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2819.html
Hopefully, it will be discussed during the next meeting of the std
committee...


Kind regards, Niels
 
S

SG

The second example shows how an rvalue ref qualifier allows move semantics
for the data of an rvalue object:

  class X {
   std::vector<char> data_;
  public:
   // ...
   std::vector<char> const & data() const & { return data_; }
   std::vector<char> && data() && { return data_; }
  };

Interesting. But this is not in line anymore with the current state of
rvalues references. It won't compile without an explicit move:

std::vector<char> && data() && { return std::move(data_); }

You may even want to return the vector by value to avoid a dangling
reference in this case:

X foo();
std::vector<char> const& bar = foo().data();

Then again, defining references to const in this way could be a thing
of the past. I hope people will rely more on copy elision and move
semantics in these cases. :)

Cheers!
SG
 
N

Niels Dekker - no reply address

class X {
Interesting. But this is not in line anymore with the current state of
rvalues references. It won't compile without an explicit move:

std::vector<char> && data() && { return std::move(data_); }

Oops! Sorry for spreading outdated information :-0 The paper is from
2005.

You may even want to return the vector by value to avoid a dangling
reference in this case:

X foo();
std::vector<char> const& bar = foo().data();

Then again, defining references to const in this way could be a thing
of the past. I hope people will rely more on copy elision and move
semantics in these cases. :)

LOL I'll try to ammend my programming style...

But in general you may not want to require that your data is
CopyConstructible (or even MoveConstructible). So you may still want to
have the rvalue-ref-qualified overload of the data() function return an
rvalue reference. Don't you think?


Kind regards, Niels
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,072
Latest member
trafficcone

Latest Threads

Top