Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I know if object passed as r-value will get moved?

I'm passing a lambda to a function which accepts it as a r-value reference.

If my lambda is defined in the function-call itself, I don't really care what happens to it later.
But if my lambda is a variable (say I want to use it more than once) I do want to know that it is not moved-from.

Is there a way to know will it be moved-from or not, making it unusable or usable accordingly after the call has returned?

EDIT:

Just to clarify, the lambda doesn't capture anything. What I care about is the functor itself: auto fn = [](int a){ return a; };

Let me make it even harder. I'll pass the functor as rvalue: std::move(fn)

std::move is only a cast. It does not move anything but the rvalue argument in the callee now binds to proper rvalue.

The question is, is fn guaranteed to get moved? Is it guaranteed to not get moved? Is there any guarantee at all? Can I make it behave this way or that way or is it up to the callee?

I want to know because I want to know can I pass fn as a function parameter twice.

EDIT #2:

Let's take another case. I have to call a function with a container. Vector, map, or whatever else. The function signature says &&. I can wrap my container with std move or std forward to get an rvalue ref into the callee. It's really the same thing as they are both just glorified casts.

Now, let's say I used std forward because I really like my container to not go anywhere.

I can easily see the callee not being aware of my intention and move my container making it invalid (gutted) after the call. Is this a language defect or am i missing something?

like image 311
BitWhistler Avatar asked Nov 04 '18 21:11

BitWhistler


People also ask

How do rvalue references work?

An rvalue reference is formed by placing an && after some type. An rvalue reference behaves just like an lvalue reference except that it can bind to a temporary (an rvalue), whereas you can not bind a (non const) lvalue reference to an rvalue.

What is an r value reference?

“r-value” refers to the data value that is stored at some address in memory. References in C++ are nothing but the alternative to the already existing variable. They are declared using the '&' before the name of the variable.

Which technique is used to invoke rvalue reference?

Introducing the magic of rvalue references C++0x has introduced a new type called rvalue reference, denoted by placing a double ampersand && after some type. Such rvalue reference lets you modify the value of a temporary object: it's like removing the const attribute in the second line above!

What's the need to move semantics?

Move semantics allows you to avoid unnecessary copies when working with temporary objects that are about to evaporate, and whose resources can safely be taken from that temporary object and used by another.


Video Answer


1 Answers

Well, if the function accept a universal reference and you want to forbid moving, there are many options for you to choose from, among others:

  1. Pass by constant reference (C++17 has std::as_const() to simplify that).
  2. Save it as a local and don't convert to rvalue-reference. Seems you do that.
  3. Use something to explicitly convert an rvalue-reference to an lvalue-reference.

Of course, unless the lambda captures locals by value which have different move-semantics than copy-semantics, and the called function actually takes advantage of that, the point is moot.

Will it actually take the opportunity?
Examine the contract, and then simply trust in it or try to verify the implementation. There is no shortcut.

Let's not even mention that C++ allows the programmer to explicitly opt out of the (limited) safety it provides.

like image 60
Deduplicator Avatar answered Nov 14 '22 23:11

Deduplicator