It would be great to have a warning that helps to identify classes with sub-optimal move semantics. Foe example it would be nice to have such a warning for cases like following: struct member { member(); member(const member&); member(member&&); private: int* data_; }; // warninig: `my_class(const my_class&)` disables the // implicit move constructor generation. Use // `my_class(my_class&) = default;` to generate it or // `my_class(my_class&) = delete;` to disable this warning. struct my_class { my_class() = default; my_class(const my_class&); private: member member1; member member2; }; void foo(my_class c); void test() { my_class c; foo(static_cast<my_class&&>(c)); // copies } The rules for the warning could be following: Issue a warning if at least one of the class members has a move constructor, class has a copy constructor and the move constructor is not implicitly deleted.
(In reply to Antony Polukhin from comment #0) > The rules for the warning could be following: > Issue a warning if at least one of the class members has a move constructor, > class has a copy constructor and the move constructor is not implicitly > deleted. I like the idea in general, but I'm not sure this rule is right, or how to workaround the warning. A class might intentionally want to copy so its members are never left in a moved-from state, so the warning would not be helpful for that class. But I can't think of a convenient way for the class author to indicate that the behaviour is as intended. They can't delete the move constructor (that makes the class non-movable), and they can't default it (that would leave members in moved-from states).
(In reply to Jonathan Wakely from comment #1) > A class might intentionally want to copy so its members are never left in a > moved-from state (In reply to Jonathan Wakely from comment #1) > They can't delete the move constructor (that makes the class non-movable) If I am not mistaken, these concepts conflict with each other. Could you describe example for such class?
You're mistaken. struct X { std::string str = "not empty"; X() = default; X(const X&) = default; }; This type does not have a move constructor. Copying an rvalue will perform a copy (not a move): X x1; X x2 = std::move(x1); // calls copy constructor But it does not have a deleted move constructor. It has no move constructor. That's different. If it had a deleted move constructor then the initialization of x2 above would fail to compile.
(In reply to Jonathan Wakely from comment #3) > X x2 = std::move(x1); // calls copy constructor Excuse me. I was sure that standard tells this row to fail compitaion
No, because that would mean almost every class written for C++03 would fail to compile in C++11 or later, which would be absurd.
Another way to workaround the warning is to use something like `my_class(my_class&) requires false;`. That's too ugly to use. I'd be fine with closing this issue as a 'won't fix'.
I think it's worth keeping open, because there might be something we can do. But I currently have no idea what it would be. See also https://gcc.gnu.org/pipermail/gcc-help/2021-May/140288.html
*** Bug 96501 has been marked as a duplicate of this bug. ***
Any ideas for a name for the flag that would control this warning?