AGML
AGML

Reputation: 920

std::move for "in-place operation"

This is probably pretty similar to other questions; I looked around a bit but I don't know what I'm talking about well enough to be sure.

I'm writing a function that "should" be in-place, but which is implemented by a BLAS call. The BLAS call is not in-place so I need to make a temporary. Thus:

void InPlace(ArrayClass& U, const TransformMatrix* M){
    ArrayClass U_temp; 
    CallBLASdgemm(U, M, U_temp);   //Now U_temp contains the correct output.
    U = std::move(U_temp);
}

Is this a valid use of std::move, or am I somehow breaking "copy elision" (or is it bad for some other reason)?

Edit: the signature of CallBLASDgemm was requested; it is

CallBLASdgemm(const ArrayClass& U, const TransformMatrix* M, 
              ArrayClass& V);

Upvotes: 0

Views: 307

Answers (3)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275330

This is valid. However, what I'd do is this:

ArrayClass myCallBLASdgemm(const ArrayClass& U, const TransformMatrix* M) {
  ArrayClass tmp;
  CallBLASdgemm(U, M, tmp);
  return tmp; // elided move
}
void InPlace(ArrayClass& U, const TransformMatrix* M){
  U = myCallBLASdgemm(U, M);
}

which runs the same code, but does it without a temporary being visible in the outer scope.

In fact, myCallBLASdgemm is so clean you can probably eliminate InPlace and just call myClassBLASdgemm where you need it.

Upvotes: 1

Hatted Rooster
Hatted Rooster

Reputation: 36463

No copies are performed with or without copy elision in this case so that's already out of the question. Because U_temp is an lvalue the compiler has to call the copy constructor if you'd do :

U = U_temp;

However, you know that U_temp won't be used anymore and thus moving away its values is completely safe and can possibly be faster (that is, if ArrayClass implements a move assignment constructor). Using std::move here is fine and even encouraged.

Upvotes: 2

NathanOliver
NathanOliver

Reputation: 180500

Yes, this is a valid use case. If you have a named temporary (lvalue) the only way to move it into U is to use std::move to cast it to a rvalue.

I think what you are worried about is when people do return std::move(object);. That is a pessimization as that copy of object into the return value can be elided in most cases.

Upvotes: 2

Related Questions