Skip to main content
deleted 25 characters in body
Source Link
Barry
  • 311.9k
  • 32
  • 734
  • 1.1k

You don't need vector, a simpler example would be just:

C1 a; C1 b(std::move(a)); // error: C1's copy constructor is deleted 

From [class.copy]:

If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if
(9.1) — X does not have a user-declared copy constructor,
(9.2) — X does not have a user-declared copy assignment operator,
(9.3) — X does not have a user-declared move assignment operator, and
(9.4) — X does not have a user-declared destructor.

C1 has a user-declared destructor, therefore it does not have a move constructor. C1 does however have an implicitly declared copy constructor

If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.

The full set of constructors on C1, explicit and implicit, looks like:

C1(); C1(C1 const& ) = delete;default; // becausebut ofalso noncopyabledelete ~C1(); 

So trying to construct a C1 from an rvalue of type C1 will match that implicitly declared copy constructor as the best match (nothing else is viable), but that constructor is deleted because noncopyable's copy constructor is deleted, so the entire expression is ill-formed.

That's why the error message mentions the constructor. That move-construction is ill-formed because the best match for that move-construction is the copy constructor is ill-formed. It can't mention the move constructor because there is no move constructor, and the destructor isn't relevant to the expression at hand. When you changed the base class to be copyable, now C1 also becomes copyable - so no error. There's still no move constructor, it's just that now there's a viable candidate for move construction.

You don't need vector, a simpler example would be just:

C1 a; C1 b(std::move(a)); // error: C1's copy constructor is deleted 

From [class.copy]:

If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if
(9.1) — X does not have a user-declared copy constructor,
(9.2) — X does not have a user-declared copy assignment operator,
(9.3) — X does not have a user-declared move assignment operator, and
(9.4) — X does not have a user-declared destructor.

C1 has a user-declared destructor, therefore it does not have a move constructor. C1 does however have an implicitly declared copy constructor

If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.

The full set of constructors on C1, explicit and implicit, looks like:

C1(); C1(C1 const& ) = delete; // because of noncopyable ~C1(); 

So trying to construct a C1 from an rvalue of type C1 will match that implicitly declared copy constructor as the best match (nothing else is viable), but that constructor is deleted because noncopyable's copy constructor is deleted, so the entire expression is ill-formed.

That's why the error message mentions the constructor. That move-construction is ill-formed because the best match for that move-construction is the copy constructor is ill-formed. It can't mention the move constructor because there is no move constructor, and the destructor isn't relevant to the expression at hand.

You don't need vector, a simpler example would be just:

C1 a; C1 b(std::move(a)); // error: C1's copy constructor is deleted 

From [class.copy]:

If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if
(9.1) — X does not have a user-declared copy constructor,
(9.2) — X does not have a user-declared copy assignment operator,
(9.3) — X does not have a user-declared move assignment operator, and
(9.4) — X does not have a user-declared destructor.

C1 has a user-declared destructor, therefore it does not have a move constructor. C1 does however have an implicitly declared copy constructor

If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.

The full set of constructors on C1, explicit and implicit, looks like:

C1(); C1(C1 const& ) = default; // but also delete ~C1(); 

So trying to construct a C1 from an rvalue of type C1 will match that implicitly declared copy constructor as the best match (nothing else is viable), but that constructor is deleted because noncopyable's copy constructor is deleted, so the entire expression is ill-formed.

That's why the error message mentions the constructor. That move-construction is ill-formed because the best match for that move-construction is the copy constructor is ill-formed. It can't mention the move constructor because there is no move constructor, and the destructor isn't relevant to the expression at hand. When you changed the base class to be copyable, now C1 also becomes copyable - so no error. There's still no move constructor, it's just that now there's a viable candidate for move construction.

added 552 characters in body
Source Link
Barry
  • 311.9k
  • 32
  • 734
  • 1.1k

You don't need vector, a simpler example would be just:

C1 a; C1 b(std::move(a)); // error: C1's copy constructor is deleted 

From [class.copy]:

If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if
(9.1) — X does not have a user-declared copy constructor,
(9.2) — X does not have a user-declared copy assignment operator,
(9.3) — X does not have a user-declared move assignment operator, and
(9.4) — X does not have a user-declared destructor.

C1 has a user-declared destructor, therefore it does not have a move constructor. C1 does however have an implicitly declared copy constructor

If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.

The full set of constructors on C1, explicit and implicit, looks like:

C1(); C1(C1 const& ) = delete; // because of noncopyable ~C1(); 

So trying to construct a C1 from an rvalue of type C1 will match thethat implicitly declared copy constructor as the best match (nothing else is viable), whichbut that constructor is deleted because noncopyable's copy constructor is deleted, so the entire expression is ill-formed.

Simpler example would be just:That's why the error message mentions the constructor. That move-construction is ill-formed because the best match for that move-construction is the copy constructor is ill-formed. It can't mention the move constructor because there is no move constructor, and the destructor isn't relevant to the expression at hand.

C1 a; C1 b(std::move(a)); // error: C1's copy constructor is deleted 

From [class.copy]:

If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if
(9.1) — X does not have a user-declared copy constructor,
(9.2) — X does not have a user-declared copy assignment operator,
(9.3) — X does not have a user-declared move assignment operator, and
(9.4) — X does not have a user-declared destructor.

C1 has a user-declared destructor, therefore it does not have a move constructor. So trying to construct a C1 from an rvalue of type C1 will match the implicitly declared copy constructor, which is deleted.

Simpler example would be just:

C1 a; C1 b(std::move(a)); // error: C1's copy constructor is deleted 

You don't need vector, a simpler example would be just:

C1 a; C1 b(std::move(a)); // error: C1's copy constructor is deleted 

From [class.copy]:

If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if
(9.1) — X does not have a user-declared copy constructor,
(9.2) — X does not have a user-declared copy assignment operator,
(9.3) — X does not have a user-declared move assignment operator, and
(9.4) — X does not have a user-declared destructor.

C1 has a user-declared destructor, therefore it does not have a move constructor. C1 does however have an implicitly declared copy constructor

If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.

The full set of constructors on C1, explicit and implicit, looks like:

C1(); C1(C1 const& ) = delete; // because of noncopyable ~C1(); 

So trying to construct a C1 from an rvalue of type C1 will match that implicitly declared copy constructor as the best match (nothing else is viable), but that constructor is deleted because noncopyable's copy constructor is deleted, so the entire expression is ill-formed.

That's why the error message mentions the constructor. That move-construction is ill-formed because the best match for that move-construction is the copy constructor is ill-formed. It can't mention the move constructor because there is no move constructor, and the destructor isn't relevant to the expression at hand.

Source Link
Barry
  • 311.9k
  • 32
  • 734
  • 1.1k

From [class.copy]:

If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if
(9.1) — X does not have a user-declared copy constructor,
(9.2) — X does not have a user-declared copy assignment operator,
(9.3) — X does not have a user-declared move assignment operator, and
(9.4) — X does not have a user-declared destructor.

C1 has a user-declared destructor, therefore it does not have a move constructor. So trying to construct a C1 from an rvalue of type C1 will match the implicitly declared copy constructor, which is deleted.

Simpler example would be just:

C1 a; C1 b(std::move(a)); // error: C1's copy constructor is deleted