Passing std :: forward_as_tuple () leads to several functions that can be moved from this rvalue-reference element of an object?

Edit: I think the most likely use case for what I'm asking for is to create a function that gets a tuple of rvalue links from std::forward_as_tuple() .

The reason for this question was that I checked the elements of the objects passed to the initializers of the constructor to see if they were rvalue references (I am open to advice saying that this is wrong, wrong, wrong ... I hope that the rule of thumb follows to avoid this in the future, but this raised a question). It occurred to me that in a slightly different context, I can end the transfer of an object that has rvalue reference members to several functions (or function objects) that I can or cannot control that can move from these members.

 template<typename... Args> void my_func(std::tuple<Args...>&& tup) { //if tup members are rvalue references, //and this function moves guts from tup members, then... func_i_dont_control(tup); //what happens here if moves are done on the same members? another_func_i_dont_control(std::move(tup)); } 

Have I looked at Using rvalue reference elements? along with some other discussions of rvalue link members, but I'm not quite able to finally sort this out.

I'm not just asking what will happen, but should this scenario happen at all or at all and what key rules should be considered when traversing objects containing rvalue link members.

+4
source share
2 answers

In this code, func_i_dont_control cannot steal the parameter silently. Only rvalues ​​are bound to rvalue references, and the named variable is not an rvalue. Your code is either not compiled, or func_i_dont_control (has overload) does not use move semantics.

To give func_i_dont_control chance to steal a tuple (bind the tuple to an rvalue link), it must be explicitly passed to rvalue using std::move(tup) .

(A function that takes a reference to an lvalue should not move from it, otherwise we really cannot say what will happen.)


Change But the question, it seems, is not what the tuple itself is, but its members. Again, these members will not be rvalues, so func_i_dont_control will need to be moved explicitly. I don’t think it has a “moral right” * to do this, unless it receives the whole tuple as an rvalue, which is not happening in your function.

* With the semantics of move, you should follow certain recommendations. Basically, you can overlay something on the rvalue and move away from it, no matter if you are dealing with lvalue or rvalue links. As long as you follow these guidelines, move-semantics will work correctly. If you start throwing things at rvalues ​​without considering these recommendations, objects will start to disappear after function calls, etc.

+1
source

Using tuples and variational patterns seems to detract from the point of the question, so let me rephrase it:

 void func(std::unique_ptr<Foo>&& foo) { std::unique_ptr<Foo> bar1(std::move(foo)); std::unique_ptr<Foo> bar2(std::move(foo)); } 

What's going on here? Well, bar2 always contains a null pointer (and bar1 may, depending on the original value of foo ).

There is no undefined behavior, because the move constructor must leave the object in a healthy state specified exactly for security reasons. Thus, you can use the object that was moved, but its state will probably not be very interesting: it should not even be equivalent to the default constructed state, it may just be outdated.

+1
source

Source: https://habr.com/ru/post/1390767/


All Articles