Consider the following classes.
struct with_copy {
    with_copy() = default;
    with_copy(with_copy const&) {}
    with_copy& operator=(with_copy const&) { return *this; }
};
struct foo {
    with_copy c;
    std::unique_ptr<int> p;
};
- Does with_copyhave a copy constructor? Yes. It was explicitly defined.
- Does with_copyhave a move constructor? No. The explicit copy constructor prevents it from being generated.
- Does with_copyhave a deleted move constructor? No. Not having a move constructor is not the same as having a deleted one. A deleted move constructor would make an attempt to move ill-formed instead of degenerating to a copy.
- Is with_copycopyable? Yes. Its copy constructor is used for copies.
- Is with_copymovable? Yes. Its copy constructor is used for moves.
... and now the tricky ones.
- Does foohave a copy constructor? Yes. It has a deleted one, as its defaulted definition would be ill-formed due to invokingunique_ptr's deleted copy constructor.
- Does foohave a move constructor? GCC says yes, clang says no.
- Does foohave a deleted move constructor? Both GCC and clang say no.
- Is foocopyable? No. Its copy constructor is deleted.
- Is foomovable? GCC says yes, clang says no.
(The behaviour is similar when one considers assignment instead of construction.)
As far as I can see, GCC is correct. foo should have a move constructor that performs a move on each member, which in with_copy's case degenerates to a copy. Clang's behaviour seems quite ridiculous: I have an aggregate with two movable members, and yet my aggregate is an immovable brick.
Who's right?
 
     
     
    