Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MoveConstructible<T>() != std::is_move_constructible<T>() #313

Closed
CaseyCarter opened this issue Jan 26, 2017 · 7 comments
Closed

MoveConstructible<T>() != std::is_move_constructible<T>() #313

CaseyCarter opened this issue Jan 26, 2017 · 7 comments

Comments

@CaseyCarter
Copy link
Collaborator

CaseyCarter commented Jan 26, 2017

...when T is const some_move_only_type due to the use of remove_cv_t in the definition of MoveConstructible. This is sensible if MoveConstructible means "Can I construct a T object from an rvalue expression with T's value type?" but becomes very surprising if we align the other `structibles with the meaning of the standard type traits.

CopyConstructible needs to change similarly for consistency.

Proposed Resolution

See P0547

@CaseyCarter
Copy link
Collaborator Author

CaseyCarter commented Jan 26, 2017

Wording in Progress:

[Editor's note: this wording assumes that the resolution of #301 has been applied, so that MoveConstructible and CopyConstructible admit non-object types.]

Change [concepts.lib.object.moveconstructible] as follows:

 template <class T>
 concept bool MoveConstructible() {
-  return Constructible<T, remove_cv_t<T>&&>() &&
-    ConvertibleTo<remove_cv_t<T>&&, T>();
+  return Constructible<T, T>() && ConvertibleTo<T, T>();
 }

-    1   Let rv be an rvalue of type remove_cv_t<T>. Then MoveConstructible<T>() is satisfied if
-(1.1) — After the definition T u = rv;, u is equal to the value of rv before the construction.
-(1.2) — T{rv} or *new T{rv} is equal to the value of rv before the construction.
-    2   rv’s resulting 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 ]
+    1   MoveConstructible<T>() is satisfied if and only if
+(1.1) — T is a non-object type, or
+(1.2) — T is an object type and the result of constructing a new object of type T from an
+        rvalue rv of type T is equal to rv's original value, leaving rv in an
+        unspecified state. [ 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 ]

Change [concepts.lib.object.copyconstructible] as follows:

 template <class T>
 concept bool CopyConstructible() {
   return MoveConstructible<T>() &&
-    Constructible<T, const remove_cv_t<T>&>() &&
-    ConvertibleTo<remove_cv_t<T>&, T>() &&
-    ConvertibleTo<const remove_cv_t<T>&, T>() &&
-    ConvertibleTo<const remove_cv_t<T>&&, T>();
+    Constructible<T, T&>() && ConvertibleTo<T&, T>() &&
+    Constructible<T, const T&>() && ConvertibleTo<const T&, T>() &&
+    Constructible<T, const T&&>() && ConvertibleTo<const T&&, T>();
 }

     1   Let v be an lvalue of type (possibly const) remove_cv_t<T> or an rvalue of type const
         remove_cv_t<T>. Then CopyConstructible<T>() is satisfied if and only if
 (1.1) — After the definition T u = v;, v is equal to u.
 (1.2) — T{v} or *new T{v} is equal to v.

@ericniebler
Copy link
Owner

Surely the semantic constraints on CopyConstructible must change, too. IMO it should get the same treatment as MoveConstructible wrt non-object types.

@ericniebler
Copy link
Owner

  • 1 MoveConstructible() is satisfied if and only if
    +(1.1) — T is a non-object type, or

Nope. void and function types are not move constructible. What I have done in the paper I'm working on is:

1 If T is an object type, then

(1.1) Let rv be an rvalue of type remove_cv_t<T>. Then MoveConstructible<T>() is satisfied if and only if

(1.1.1) -- After the definition T u = rv;, u is equal to the value of rv before the construction.

(1.1.2) -- T{rv} or *new T{rv} is equal to the value of rv before the construction.

(1.2) If T is not const, rv's resulting state is unspecified; otherwise, it is unchanged. [ 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 ]

I don't bother saying, "Otherwise, MoveConstructable adds no further semantic constraints on its argument," but that's the gist.

@CaseyCarter
Copy link
Collaborator Author

CaseyCarter commented Jan 26, 2017

Surely the semantic constraints on CopyConstructible must change, too.

Yes, WIP. Distracted integrating cmcstl2 pulls.

Nope. void and function types are not move constructible.

They fail syntactically in Constructible, and hence need no semantic requirements here.

@ericniebler
Copy link
Owner

So text which reads, "MoveConstructible() is satisfied if and only if T is a non-object type, or..." is wrong. I guess I'm confused about what you're suggesting.

@CaseyCarter
Copy link
Collaborator Author

The prose requirements are implicitly in addition to the syntactic requirements, here as in all of the other concepts.

@ericniebler
Copy link
Owner

But they should not be in contradiction of it.

@ericniebler ericniebler added ready and removed review labels Jul 12, 2017
CaseyCarter added a commit that referenced this issue Jul 18, 2017
CaseyCarter added a commit that referenced this issue Jul 18, 2017
CaseyCarter added a commit that referenced this issue Jul 18, 2017
CaseyCarter added a commit that referenced this issue Jul 18, 2017
CaseyCarter added a commit that referenced this issue Jul 18, 2017
CaseyCarter added a commit that referenced this issue Jul 18, 2017
CaseyCarter added a commit that referenced this issue Jul 18, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants