diff --git a/stl/inc/expected b/stl/inc/expected index a0f05bd8eea..93fbfcf0843 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -238,14 +238,15 @@ public: // clang-format on template - static constexpr bool _Allow_unwrapping = !is_constructible_v<_Ty, expected<_Uty, _UErr>&> // - && !is_constructible_v<_Ty, expected<_Uty, _UErr>> // - && !is_constructible_v<_Ty, const expected<_Uty, _UErr>&> // - && !is_constructible_v<_Ty, const expected<_Uty, _UErr>> // - && !is_convertible_v&, _Ty> // - && !is_convertible_v&&, _Ty> // - && !is_convertible_v&, _Ty> // - && !is_convertible_v&&, _Ty> // + static constexpr bool _Allow_unwrapping = disjunction_v, bool>, + negation&>, // + is_constructible<_Ty, expected<_Uty, _UErr>>, // + is_constructible<_Ty, const expected<_Uty, _UErr>&>, // + is_constructible<_Ty, const expected<_Uty, _UErr>>, // + is_convertible&, _Ty>, // + is_convertible&&, _Ty>, // + is_convertible&, _Ty>, // + is_convertible&&, _Ty>>>> // && !is_constructible_v, expected<_Uty, _UErr>&> // && !is_constructible_v, expected<_Uty, _UErr>> // && !is_constructible_v, const expected<_Uty, _UErr>&> // @@ -280,7 +281,9 @@ public: template requires (!is_same_v, in_place_t> && !is_same_v, expected> - && !_Is_specialization_v, unexpected> && is_constructible_v<_Ty, _Uty>) + && !_Is_specialization_v, unexpected> + && (!is_same_v, bool> || !_Is_specialization_v, expected>) + && is_constructible_v<_Ty, _Uty>) constexpr explicit(!is_convertible_v<_Uty, _Ty>) expected(_Uty&& _Other) noexcept(is_nothrow_constructible_v<_Ty, _Uty>) // strengthened : _Value(_STD forward<_Uty>(_Other)), _Has_value(true) {} diff --git a/stl/inc/optional b/stl/inc/optional index a86eaa23be7..01269d4c114 100644 --- a/stl/inc/optional +++ b/stl/inc/optional @@ -239,7 +239,9 @@ public: template using _AllowDirectConversion = bool_constant, optional>>, - negation, in_place_t>>, is_constructible<_Ty, _Ty2>>>; + negation, in_place_t>>, + negation, bool>, _Is_specialization<_Remove_cvref_t<_Ty2>, optional>>>, + is_constructible<_Ty, _Ty2>>>; template ::value, int> = 0> constexpr explicit(!is_convertible_v<_Ty2, _Ty>) @@ -247,11 +249,13 @@ public: : _Mybase(in_place, _STD forward<_Ty2>(_Right)) {} template - struct _AllowUnwrapping : bool_constant, is_constructible<_Ty, optional<_Ty2>&>, - is_constructible<_Ty, const optional<_Ty2>&>, - is_constructible<_Ty, const optional<_Ty2>>, is_constructible<_Ty, optional<_Ty2>>, - is_convertible&, _Ty>, is_convertible&, _Ty>, - is_convertible, _Ty>, is_convertible, _Ty>>> {}; + struct _AllowUnwrapping + : bool_constant, bool>, + negation, is_constructible<_Ty, optional<_Ty2>&>, + is_constructible<_Ty, const optional<_Ty2>&>, is_constructible<_Ty, const optional<_Ty2>>, + is_constructible<_Ty, optional<_Ty2>>, is_convertible&, _Ty>, + is_convertible&, _Ty>, is_convertible, _Ty>, + is_convertible, _Ty>>>>> {}; template , is_constructible<_Ty, const _Ty2&>>, int> = 0> diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 2d41f7f11b8..cdd96775d45 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -120,6 +120,9 @@ std/language.support/support.limits/support.limits.general/format.version.compil # libc++ doesn't implement LWG-3670 std/ranges/range.factories/range.iota.view/iterator/member_typedefs.compile.pass.cpp FAIL +# libc++ doesn't implement LWG-3836 +std/utilities/expected/expected.expected/ctor/ctor.u.pass.cpp FAIL + # libc++ doesn't implement LWG-3857 std/strings/string.view/string.view.cons/from_range.pass.cpp FAIL std/strings/string.view/string.view.cons/from_string1.compile.fail.cpp FAIL diff --git a/tests/std/tests/P0220R1_optional/test.cpp b/tests/std/tests/P0220R1_optional/test.cpp index 77d3497fde1..aee3c2a6f34 100644 --- a/tests/std/tests/P0220R1_optional/test.cpp +++ b/tests/std/tests/P0220R1_optional/test.cpp @@ -8148,6 +8148,30 @@ namespace msvc { STATIC_ASSERT(!is_constructible_v); } // namespace lwg2842 + namespace lwg3836 { + STATIC_ASSERT(std::is_convertible_v, std::optional>); + STATIC_ASSERT(std::is_convertible_v&, std::optional>); + +#if _HAS_CXX20 +#define CONSTEXPR20 constexpr +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv +#define CONSTEXPR20 inline +#endif // ^^^ !_HAS_CXX20 ^^^ + CONSTEXPR20 bool run_test() { + std::optional oi = 0; + std::optional ob = oi; + assert(!ob.value()); + assert(!std::optional{std::optional{0}}.value()); + + return true; + } +#undef CONSTEXPR20 + +#if _HAS_CXX20 + STATIC_ASSERT(run_test()); +#endif // _HAS_CXX20 + } // namespace lwg3836 + namespace vso406124 { // Defend against regression of VSO-406124 void run_test() { @@ -8334,6 +8358,8 @@ int main() { nonmembers::make_optional_explicit_init_list::run_test(); nonmembers::swap_::run_test(); + msvc::lwg3836::run_test(); + msvc::vso406124::run_test(); msvc::vso508126::run_test(); msvc::vso614907::run_test(); diff --git a/tests/std/tests/P0323R12_expected/test.cpp b/tests/std/tests/P0323R12_expected/test.cpp index 14bfc85b158..546077a1ea5 100644 --- a/tests/std/tests/P0323R12_expected/test.cpp +++ b/tests/std/tests/P0323R12_expected/test.cpp @@ -662,6 +662,14 @@ namespace test_expected { test_constructors(); test_constructors(); test_constructors(); + + // LWG-3836 + struct BaseError {}; + struct DerivedError : BaseError {}; + + std::expected e1(false); + std::expected e2(e1); + assert(!e2.value()); } template