[libcxx-commits] [libcxx] 7ded345 - [libc++] Implement LWG3940: std::expected<void, E>::value() also needs E to be copy constructible (#71819)

via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jan 19 02:06:16 PST 2024


Author: Twice
Date: 2024-01-19T10:06:11Z
New Revision: 7ded34576f348d8f5b915deb53e8bfa45f72c79c

URL: https://github.com/llvm/llvm-project/commit/7ded34576f348d8f5b915deb53e8bfa45f72c79c
DIFF: https://github.com/llvm/llvm-project/commit/7ded34576f348d8f5b915deb53e8bfa45f72c79c.diff

LOG: [libc++] Implement LWG3940: std::expected<void, E>::value() also needs E to be copy constructible (#71819)

This patch includes the fix for
[LWG3940](https://cplusplus.github.io/LWG/issue3940)
(`std::expected<void, E>::value()` also needs `E` to be copy
constructible)

Added: 
    libcxx/test/libcxx/utilities/expected/expected.void/value.lwg3940.verify.cpp

Modified: 
    libcxx/docs/Status/Cxx2cIssues.csv
    libcxx/include/__expected/expected.h
    libcxx/test/std/utilities/expected/expected.void/observers/value.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index fe0f13f6e8cb2c..e03b7c783bc38b 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -15,7 +15,7 @@
 "`3927 <https://wg21.link/LWG3927>`__","Unclear preconditions for ``operator[]`` for sequence containers","Varna June 2023","|Nothing To Do|","",""
 "`3935 <https://wg21.link/LWG3935>`__","``template<class X> constexpr complex& operator=(const complex<X>&)`` has no specification","Varna June 2023","|Complete|","3.4",""
 "`3938 <https://wg21.link/LWG3938>`__","Cannot use ``std::expected`` monadic ops with move-only ``error_type``","Varna June 2023","|Complete|","18.0",""
-"`3940 <https://wg21.link/LWG3940>`__","``std::expected<void, E>::value()`` also needs ``E`` to be copy constructible","Varna June 2023","","",""
+"`3940 <https://wg21.link/LWG3940>`__","``std::expected<void, E>::value()`` also needs ``E`` to be copy constructible","Varna June 2023","|Complete|","18.0",""
 "","","","","",""
 "`2392 <https://wg21.link/LWG2392>`__","""character type"" is used but not defined","Kona November 2023","","",""
 "`3203 <https://wg21.link/LWG3203>`__","``span`` element access invalidation","Kona November 2023","","",""

diff  --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index 97f92bdfe44c4e..9f36c41b78edfd 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -1150,12 +1150,14 @@ class expected<_Tp, _Err> {
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr void value() const& {
+    static_assert(is_copy_constructible_v<_Err>);
     if (!__has_val_) {
       std::__throw_bad_expected_access<_Err>(__union_.__unex_);
     }
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr void value() && {
+    static_assert(is_copy_constructible_v<_Err> && is_move_constructible_v<_Err>);
     if (!__has_val_) {
       std::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_));
     }

diff  --git a/libcxx/test/libcxx/utilities/expected/expected.void/value.lwg3940.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/value.lwg3940.verify.cpp
new file mode 100644
index 00000000000000..9c1c1d2e648d6a
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/value.lwg3940.verify.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// UNSUPPORTED: no-rtti
+// UNSUPPORTED: no-exceptions
+
+// constexpr void value() const &;
+// Mandates: is_copy_constructible_v<E> is true.
+
+// constexpr void value() &&;
+// Mandates: is_copy_constructible_v<E> is true and is_move_constructible_v<E> is true.
+
+#include <expected>
+
+#include "MoveOnly.h"
+
+struct CopyOnly {
+  CopyOnly()                = default;
+  CopyOnly(const CopyOnly&) = default;
+  CopyOnly(CopyOnly&&)      = delete;
+};
+
+void test() {
+  // MoveOnly type as error_type
+  std::expected<void, MoveOnly> e(std::unexpect, 5);
+
+  e.value(); // expected-note {{in instantiation of member function 'std::expected<void, MoveOnly>::value' requested here}}
+  // expected-error@*:* {{static assertion failed due to requirement 'is_copy_constructible_v<MoveOnly>'}}
+  // expected-error@*:* {{call to deleted constructor of 'MoveOnly'}}
+
+  std::move(e)
+      .value(); // expected-note {{in instantiation of member function 'std::expected<void, MoveOnly>::value' requested here}}
+  // expected-error@*:* {{static assertion failed due to requirement 'is_copy_constructible_v<MoveOnly>'}}
+
+  // CopyOnly type as error_type
+  std::expected<void, CopyOnly> e2(std::unexpect);
+  // expected-error@*:* {{call to deleted constructor of 'CopyOnly'}}
+
+  e2.value();
+
+  std::move(e2)
+      .value(); // expected-note {{in instantiation of member function 'std::expected<void, CopyOnly>::value' requested here}}
+  // expected-error@*:* {{static assertion failed due to requirement 'is_move_constructible_v<CopyOnly>'}}
+  // expected-error@*:* {{call to deleted constructor of 'CopyOnly'}}
+}

diff  --git a/libcxx/test/std/utilities/expected/expected.void/observers/value.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/observers/value.pass.cpp
index 0f02db19c7b75e..a24d67c57e19b5 100644
--- a/libcxx/test/std/utilities/expected/expected.void/observers/value.pass.cpp
+++ b/libcxx/test/std/utilities/expected/expected.void/observers/value.pass.cpp
@@ -65,17 +65,6 @@ void testException() {
     }
   }
 
-  // MoveOnly
-  {
-    std::expected<void, MoveOnly> e(std::unexpect, 5);
-    try {
-      std::move(e).value();
-      assert(false);
-    } catch (const std::bad_expected_access<MoveOnly>& ex) {
-      assert(ex.error() == 5);
-    }
-  }
-
 #endif // TEST_HAS_NO_EXCEPTIONS
 }
 


        


More information about the libcxx-commits mailing list