Move construction from const link

I have the following situation when I need to move construct t2 from t1. Unfortunately, this cannot be done (suppose a violation of fatigue)
What is the correct approach to transparently calling from the calling user foo? (i.e., without having to pass by value and explicit std :: move)

struct T { T() = default; ~T() = default; T(T&&) = default; }; T foo(const T& t) { T t3; if (predicate) return t3; else return std::move(t); } int main() { T t1; T t2 = foo(t1); return 0; } 
+4
source share
3 answers

You could do this if you wanted bad enough. To do this, your foo will end up as essentially reimplementing std::move .

 struct T { T() = default; ~T() = default; T(T&&) = default; }; template<class T> struct my_remove_reference {typedef T type;}; template<class T> struct my_remove_reference<T&> {typedef T type;}; // The third part of a normal `remove_reference`, but which we don't need in // this case (though it'll all still be fine if you un-comment this). //template<class T> struct my_remove_reference<T&&> {typedef T type;}; template <typename T> typename my_remove_reference<T>::type &&foo(T &&t) { return static_cast<typename my_remove_reference<T>::type &&>(t); } int main() { T t1; T t2 = foo(t1); return 0; } 

Now, despite the fact that you can / could do it, the other answers remain more or less correct - although you can do it, you almost certainly shouldn't. If you used this foo in a real class that supports relocation (i.e. it really moves state from source to destination), you end up destroying the original object, even if it remains visible.

Doing this with the help of an edited question, where foo can, but not always, destroy the original object will be especially detrimental. With the right name, which makes it clear that foo really moves from the source, it might be hardly wise to do this, but (at least for me) a function that may or may not destroy its argument seems to be significantly worse than that That makes it reliable. Obviously, the version of foo , as mentioned above, just does the same thing as std::move , is pointless, but the version that also did some other input processing (and for some reason could not be used with std::move ) may be hardly acceptable if you really have no other choice.

+4
source

What is the correct approach to transparently calling from the calling user foo?

You cannot do this, and that was so. Lvalue never moves from transparent.

Since the moved object usually remains in an unknown (but legal) state, it would be dangerous if the client could pass the lvalue value as an argument to the function, and this function was allowed to silently pass from it. A client can be left as a zombie object without even knowing it!

Therefore, the language enforces the rule that moving from an lvalue must be a conscious action and must occur by explicitly turning the lvalue into an rvalue (actually, an xvalue) by calling std::move() .

In this case, I would say that your function foo() - what it really should do, should take the rvalue reference, and the client should call it like this:

 T t2 = foo(std::move(t1)); 

Note that this last sentence may not be correct after you turn a meaningless name, such as foo() , into something that reflects the semantics of a particular operation in a particular program. However, not knowing what the meaning of this operation is, I can only provide official, mechanical advice on how to compile code and how to think about the semantics of movement in general.

+5
source

without requiring passing by value and explicit std :: move

C ++ does not allow you to move things without at least one of them. This is by design.

The basic rule of motion in C ++ is that it is not allowed by accident. If you have an lvalue value and want to pass it to some functions that can pass from it, then you, as the caller, should use std::move . This is by design, so it’s clear that the caller’s goal is to move the object out.

That way, when you look at the code, you can see if you accidentally used the moved value incorrectly, without having to see anything more than an explicit use of std::move .

What you need is not what you need.

+3
source

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


All Articles