All CopyConstructible types of type MoveConstructible?

According to working draft N3337 (the most similar project for the published ISOC ++ 11 standard) and cppreference.com , the answer is yes.

N3337:

Table 21 - Copy requirements (in addition to MoveConstructible) [copyconstructible] [...]

cppreference.com :

Type T satisfies CopyConstructible if

  • Type T satisfies MoveConstructible and [...]

But according to the result of compiling main.cpp with gcc (Ubuntu 4.8.4-2ubuntu1 ~ 14.04) 4.8.4 and running a.out with the quoted operators in Ubuntu 14.04.3 LTS, the answer is not like that.

main.cpp:

#include <iostream> #include <type_traits> struct As { As()=default; As(As&&)=delete; As(const As&)=default; As& operator=(As&&)=delete; As& operator=(const As&)=delete; ~As()=default; }; int main() { std::cout<<std::is_move_constructible<As>::value<<std::endl; std::cout<<std::is_copy_constructible<As>::value<<std::endl; return 0; } 

compilation and launch from the terminal:

 $ g++ -std=c++11 main.cpp $ ./a.out 

result (output):

 0 1 

Am I misunderstood something, or is N3337 and cppreference.com wrong, or does gcc contain an error?

+5
source share
3 answers

std::is_copy_constructible<T> is defined as exactly std::is_constructible<T, const T&> , i.e. it only checks that building from const lvalue is possible, it does not check all the properties of the CopyConstructible concept.

So your test does not show what you think it shows. Your type is not a CopyConstructible type because it does not meet some other requirements.

Regarding the original question, yes. Because all CopyConstructible types must meet the requirements for MoveConstructible, all of them are MoveConstructible types. MoveConstructible does not require anything to be moved, only this construction from rvalues ​​is possible, and all types of CopyConstructible can be built from rvalues ​​(even if they can make a deep copy, not move).

You can create corrupt types that can be copied from lvalues, but not from rvalues, or can be copied from const lvalues, but not unconsolidated lvalues ​​and other abominations. Such types are not CopyConstructible and do not work with the standard C ++ library. There are very few good reasons to ever create such vicious types.

+8
source

Your example deceives you a little.

 As(As&&)=delete; 

By removing the move constructor, you make it illegal to build As with As&& , although the copy constructor may be called instead because it refers to const.

An example that displays the behavior you are looking for is the following:

 struct As { As()=default; As(const As&)=default; As& operator=(As&&)=delete; As& operator=(const As&)=delete; ~As()=default; }; 

I just deleted the removal of the move constructor. As will not have a move constructor implicitly declared because it has a bunch of other user-declared special functions *. If you run your tests in this example, you will see that the class moves constructively, even if it does not have a move constructor.

Live demo


* Specifically, a move constructor will not be declared implicitly if there is a copy constructor declared by the user, a copy destination operator, a move destination operator, or a destructor.

+6
source

is_copy_constructible does not require the type to be movable. When he speaks

CopyConstructible requirements (in addition to MoveConstructible) [copyconstructible]

This means that for CopyConstructible, the class must satisfy the MoveConstructible requirements, which are

 T u = rv; u is equivalent to the value of rv before the construction T(rv) T(rv) is equivalent to the value of rv before the construction rv's state is unspecified. [ Note: rv must still meet the requirements of the library component that is using it. The operations listed in those requirements must work as specified whether rv has been moved from or not. — end note ] 

In addition to [copyconstructible]

 T u = v; the value of v is unchanged and is equivalent to u T(v) the value of v is unchanged and is equivalent to T(v) 

The reason std::is_move_constructible<As>::value is incorrect: you have a remote constrcutor host that prohibits the move construct. For this to be true, a constructor without remote movements and a satisfying [moveconstructible] is required.

+2
source

Source: https://habr.com/ru/post/1241629/


All Articles