Skip to content

Commit f140c37

Browse files
committed
[libc++] Implement LWG4222 'expected' constructor from a single value missing a constraint
Signed-off-by: yronglin <[email protected]>
1 parent e977b28 commit f140c37

File tree

3 files changed

+14
-2
lines changed

3 files changed

+14
-2
lines changed

libcxx/docs/Status/Cxx2cIssues.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@
132132
"`LWG4200 <https://wg21.link/LWG4200>`__","The ``operation_state`` concept can be simplified","2025-06 (Sofia)","","",""
133133
"`LWG4201 <https://wg21.link/LWG4201>`__","``with-await-transform::await_transform`` should not use a deduced return type","2025-06 (Sofia)","","",""
134134
"`LWG4217 <https://wg21.link/LWG4217>`__","Clarify ``mdspan`` layout mapping requirements for ``rank == 0``","2025-06 (Sofia)","","",""
135-
"`LWG4222 <https://wg21.link/LWG4222>`__","``expected`` constructor from a single value missing a constraint","2025-06 (Sofia)","","",""
135+
"`LWG4222 <https://wg21.link/LWG4222>`__","``expected`` constructor from a single value missing a constraint","2025-06 (Sofia)","|Complete|","22",""
136136
"`LWG4224 <https://wg21.link/LWG4224>`__","Philox engines should be freestanding","2025-06 (Sofia)","","",""
137137
"`LWG4227 <https://wg21.link/LWG4227>`__","Missing ``noexcept`` operator in [exec.when.all]","2025-06 (Sofia)","","",""
138138
"`LWG4231 <https://wg21.link/LWG4231>`__","``datapar::chunk<N>`` should use ``simd-size-type`` instead of ``size_t``","2025-06 (Sofia)","","",""

libcxx/include/__expected/expected.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,8 @@ class expected : private __expected_base<_Tp, _Err> {
557557

558558
template <class _Up = _Tp>
559559
requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> &&
560-
is_constructible_v<_Tp, _Up> && !__is_std_unexpected<remove_cvref_t<_Up>>::value &&
560+
!is_same_v<remove_cvref_t<_Up>, unexpect_t> && is_constructible_v<_Tp, _Up> &&
561+
!__is_std_unexpected<remove_cvref_t<_Up>>::value &&
561562
(!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_expected<remove_cvref_t<_Up>>::value))
562563
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>)
563564
expected(_Up&& __u) noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened

libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.u.pass.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
// Constraints:
1515
// - is_same_v<remove_cvref_t<U>, in_place_t> is false; and
1616
// - is_same_v<expected, remove_cvref_t<U>> is false; and
17+
// - is_same_v<remove_cvref_t<U>, unexpect_t> is false; and
1718
// - remove_cvref_t<U> is not a specialization of unexpected; and
1819
// - is_constructible_v<T, U> is true.
1920
//
@@ -46,6 +47,16 @@ static_assert(!std::is_constructible_v<std::expected<FromJustInplace, int>, std:
4647
// Note that result is true because it is covered by the constructors that take expected
4748
static_assert(std::is_constructible_v<std::expected<int, int>, std::expected<int, int>&>);
4849

50+
struct T {
51+
explicit T(auto) {}
52+
};
53+
struct E {
54+
E(int) {}
55+
};
56+
57+
// is_same_v<remove_cvref_t<U>, unexpect_t> is false;
58+
static_assert(!std::is_constructible_v<std::expected<T, E>, std::unexpect_t>);
59+
4960
// remove_cvref_t<U> is a specialization of unexpected
5061
// Note that result is true because it is covered by the constructors that take unexpected
5162
static_assert(std::is_constructible_v<std::expected<int, int>, std::unexpected<int>&>);

0 commit comments

Comments
 (0)