Bug 89700 - Warn if move constructor is not generated and not deleted
Summary: Warn if move constructor is not generated and not deleted
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 9.0
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
: 96501 (view as bug list)
Depends on:
Blocks: new-warning, new_warning
  Show dependency treegraph
 
Reported: 2019-03-13 12:19 UTC by Antony Polukhin
Modified: 2021-10-27 05:15 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-05-14 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Antony Polukhin 2019-03-13 12:19:32 UTC
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.
Comment 1 Jonathan Wakely 2019-03-13 15:10:26 UTC
(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).
Comment 2 Igor Klevanets 2019-03-13 18:29:05 UTC
(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?
Comment 3 Jonathan Wakely 2019-03-13 22:26:35 UTC
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.
Comment 4 Igor Klevanets 2019-03-14 08:31:36 UTC
(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
Comment 5 Jonathan Wakely 2019-03-14 11:58:35 UTC
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.
Comment 6 Antony Polukhin 2019-03-25 14:17:08 UTC
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'.
Comment 7 Jonathan Wakely 2021-05-14 13:16:53 UTC
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
Comment 8 Jonathan Wakely 2021-05-19 16:13:41 UTC
*** Bug 96501 has been marked as a duplicate of this bug. ***
Comment 9 Eric Gallager 2021-10-27 05:15:15 UTC
Any ideas for a name for the flag that would control this warning?