Is it possible to return the current object if it is an r-value reference?
Asked Answered
G

1

11

I have recently learned about r-value references. In order to more thoroughly experiment I decided to write a simple DenseMatrix class. My question is is it possible to write any function ( Transpose for this example ) such that for auto A = B.Transpose() separate matrix is returned, but for auto A = (B + C).Transpose() the result of the Transpose is calculated in place?

Gethsemane answered 17/7, 2020 at 16:50 Comment(0)
V
16

Yes, you can overload the Transpose member function on the ref-qualification of the object it's being called on:

class DenseMatrix {
 
  DenseMatrix Transpose() const & {  // #1 called on l-values
     auto copy = *this;
     // transpose copy
     return copy;
  }

  DenseMatrix&& Transpose() && {  // #2 called on r-values
     // transpose *this
     return std::move(*this);
  }
};

So you get the result:

B.Transpose();        // calls #1
(B + C).Transpose();  // calls #2

Here's a demo.

Note that you could implement the l-value overload in terms of the r-value overload, like this:

DenseMatrix Transpose() const & {  
  auto copy = *this;
  return std::move(copy).Transpose();
}

Here's a demo.

Varioloid answered 17/7, 2020 at 16:57 Comment(9)
Why not DenseMatrix&& Transpose() &&? I.e. modifying an r-value in-place.Scribbler
@MaximEgorushkin I thought of that, but it feels like copy elision would take care of that. I'm not sure though. Edited anyway, since it can't hurt at least.Varioloid
@Varioloid this is a hidden function argument, and returning a function argument prevents return-value optimization and because this is not an object with automatic storage duration here. See en.cppreference.com/w/cpp/language/copy_elision : In a return statement, when the operand is the name of a non-volatile object with automatic storage duration, which isn't a function parameter or a catch clause parameter, and which is of the same class type (ignoring cv-qualification) as the function return type. This variant of copy elision is known as NRVO, "named return value optimization".Scribbler
@MaximEgorushkin Aah, ok, that makes sense, thanks. It could still be optimized, but it's not guaranteed to.Varioloid
Why there is && after #2 Transpose()? I am unfamiliar with this syntaxCaras
It's the syntax that constrains the function to be called on r-values. In fact this syntax was introduced in c++11 to achieve exactly the effect you're looking for :)Varioloid
@Varioloid where is this documented? I am googling and I can't find it.Caras
@bar3 en.cppreference.com/w/cpp/language/…Scribbler
For a somewhat exhaustive general Q&A on ref-qualifiers, see What does the & (ampersand) at the end of member function signature mean?.Bergstrom

© 2022 - 2024 — McMap. All rights reserved.