Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
208 views
in Technique[技术] by (71.8m points)

c++ - Why is the move constructor neither declared nor deleted with clang?

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_copy have a copy constructor? Yes. It was explicitly defined.
  • Does with_copy have a move constructor? No. The explicit copy constructor prevents it from being generated.
  • Does with_copy have 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_copy copyable? Yes. Its copy constructor is used for copies.
  • Is with_copy movable? Yes. Its copy constructor is used for moves.

... and now the tricky ones.

  • Does foo have a copy constructor? Yes. It has a deleted one, as its defaulted definition would be ill-formed due to invoking unique_ptr's deleted copy constructor.
  • Does foo have a move constructor? GCC says yes, clang says no.
  • Does foo have a deleted move constructor? Both GCC and clang say no.
  • Is foo copyable? No. Its copy constructor is deleted.
  • Is foo movable? 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

C++11, or rather n3485, [class.copy]/9:

If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if

  • X does not have a user-declared copy constructor,
  • X does not have a user-declared copy assignment operator,
  • X does not have a user-declared move assignment operator,
  • X does not have a user-declared destructor, and
  • the move constructor would not be implicitly defined as deleted.

and /11:

An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy/ move constructor for a class X is defined as deleted (8.4.3) if X has:

  • [...]
  • for the copy constructor, a non-static data member of rvalue reference type, or
  • for the move constructor, a non-static data member or direct or virtual base class with a type that does not have a move constructor and is not trivially copyable.

As with_copy is not trivially copyable, foo will have no move-constructor (it would be defined as deleted, therefore it won't be implicitly declared).


C++1y, or rather github repo commit e31867c0 from 2013-11-12; incorporating DR1402:

/9:

If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if

  • X does not have a user-declared copy constructor,
  • X does not have a user-declared copy assignment operator,
  • X does not have a user-declared move assignment operator, and
  • X does not have a user-declared destructor.

and /11:

An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy/ move constructor for a class X is defined as deleted (8.4.3) if X has:

  • [...]
  • for the copy constructor, a non-static data member of rvalue reference type.

A defaulted move constructor that is defined as deleted is ignored by overload resolution (13.3, 13.4).

Here, foo will have a move-constructor.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...