From 408091d1f867527d914688c7d5c94400629d70f7 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Wed, 25 Jan 2023 14:06:40 +0000 Subject: [PATCH 01/50] Implement P2505R5 Monadic Functions for std::expected --- stl/inc/expected | 613 ++++++++++++++++++ .../env.lst | 4 + .../test.cpp | 332 ++++++++++ 3 files changed, 949 insertions(+) create mode 100644 tests/std/tests/P2505R5_monadic_functions_for_expected/env.lst create mode 100644 tests/std/tests/P2505R5_monadic_functions_for_expected/test.cpp diff --git a/stl/inc/expected b/stl/inc/expected index 8b2399f7851..5674bfadf00 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -160,6 +160,10 @@ _EXPORT_STD struct unexpect_t { _EXPORT_STD inline constexpr unexpect_t unexpect{}; +struct _Construct_expected_from_invoke_result_tag { + explicit _Construct_expected_from_invoke_result_tag() = default; +}; + _EXPORT_STD template class expected { static_assert(!is_reference_v<_Ty>, "T must not be a reference type. (N4910 [expected.object.general]/2)"); @@ -685,6 +689,303 @@ public: } } + template + _NODISCARD constexpr _Err error_or(_Uty&& _Other) const& noexcept( + is_nothrow_copy_constructible_v<_Err>&& is_nothrow_convertible_v<_Uty, _Err>) { // strengthened + static_assert( + is_copy_constructible_v<_Err>, "is_copy_constructible_v must be true. (N4928 [expected.object.obs]/20)"); + static_assert( + is_convertible_v<_Uty, _Err>, "is_convertible_v must be true. (N4928 [expected.object.obs]/20)"); + + if (_Has_value) { + return _STD forward<_Uty>(_Other); + } else { + return _Unexpected; + } + } + + template + _NODISCARD constexpr _Err error_or(_Uty&& _Other) && noexcept( + is_nothrow_move_constructible_v<_Err>&& is_nothrow_convertible_v<_Uty, _Err>) { // strengthened + static_assert( + is_move_constructible_v<_Err>, "is_move_constructible_v must be true. (N4928 [expected.object.obs]/22)"); + static_assert( + is_convertible_v<_Uty, _Err>, "is_convertible_v must be true. (N4928 [expected.object.obs]/22)"); + + if (_Has_value) { + return _STD forward<_Uty>(_Other); + } else { + return _STD move(_Unexpected); + } + } + + // [expected.object.monadic] + + template + requires is_copy_constructible_v<_Err> + constexpr auto and_then(_Fn&& _Func) & { + using _Uty = remove_cvref_t>; + + static_assert(_Is_specialization_v<_Uty, expected>, + "expected::and_then(F) requires the return type of F to be a specialization of expected " + "N4928 [expected.object.monadic]/3."); + + if (this->_Has_value) { + return _STD invoke(_STD forward<_Fn>(_Func), this->_Value); + } else { + return _Uty(unexpect, this->_Unexpected); + } + } + + template + requires is_copy_constructible_v<_Err> + constexpr auto and_then(_Fn&& _Func) const& { + using _Uty = remove_cvref_t>; + + static_assert(_Is_specialization_v<_Uty, expected>, + "expected::and_then(F) requires the return type of F to be a specialization of expected " + "N4928 [expected.object.monadic]/3."); + + if (this->_Has_value) { + return _STD invoke(_STD forward<_Fn>(_Func), this->_Value); + } else { + return _Uty(unexpect, this->_Unexpected); + } + } + + template + requires is_move_constructible_v<_Err> + constexpr auto and_then(_Fn&& _Func) && { + using _Uty = remove_cvref_t>; + + static_assert(_Is_specialization_v<_Uty, expected>, + "expected::and_then(F) requires the return type of F to be a specialization of expected " + "N4928 [expected.object.monadic]/7."); + + if (this->_Has_value) { + return _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Value)); + } else { + return _Uty(unexpect, _STD move(this->_Unexpected)); + } + } + + template + requires is_move_constructible_v<_Err> + constexpr auto and_then(_Fn&& _Func) const&& { + using _Uty = remove_cvref_t>; + + static_assert(_Is_specialization_v<_Uty, expected>, + "expected::and_then(F) requires the return type of F to be a specialization of optional " + "N4928 [expected.object.monadic]/7."); + + if (this->_Has_value) { + return _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Value)); + } else { + return _Uty(unexpect, _STD move(this->_Unexpected)); + } + } + + template + requires is_copy_constructible_v<_Ty> + constexpr auto or_else(_Fn&& _Func) & { + using _Uty = remove_cvref_t>; + + static_assert(_Is_specialization_v<_Uty, expected>, + "expected::or_else(F) requires the return type of F to be a specialization of expected " + "N4928 [expected.object.monadic]/11."); + static_assert(is_same_v, + "expected::or_else(F) requires the value type of the return type of F to be T" + "N4928 [expected.object.monadic]/11."); + + if (this->_Has_value) { + return _Uty(in_place, this->_Value); + } else { + return _STD invoke(_STD forward<_Fn>(_Func), this->_Unexpected); + } + } + + template + requires is_copy_constructible_v<_Ty> + constexpr auto or_else(_Fn&& _Func) const& { + using _Uty = remove_cvref_t>; + + static_assert(_Is_specialization_v<_Uty, expected>, + "expected::or_else(F) requires the return type of F to be a specialization of expected " + "N4928 [expected.object.monadic]/11."); + static_assert(is_same_v, + "expected::or_else(F) requires the value type of the return type of F to be T" + "N4928 [expected.object.monadic]/11."); + + if (this->_Has_value) { + return _Uty(in_place, this->_Value); + } else { + return _STD invoke(_STD forward<_Fn>(_Func), this->_Unexpected); + } + } + + template + requires is_move_constructible_v<_Ty> + constexpr auto or_else(_Fn&& _Func) && { + using _Uty = remove_cvref_t>; + + static_assert(_Is_specialization_v<_Uty, expected>, + "expected::or_else(F) requires the return type of F to be a specialization of expected " + "N4928 [expected.object.monadic]/11."); + static_assert(is_same_v, + "expected::or_else(F) requires the value type of the return type of F to be T" + "N4928 [expected.object.monadic]/11."); + + if (this->_Has_value) { + return _Uty(in_place, _STD move(this->_Value)); + } else { + return _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Unexpected)); + } + } + + template + requires is_move_constructible_v<_Ty> + constexpr auto or_else(_Fn&& _Func) const&& { + using _Uty = remove_cvref_t>; + + static_assert(_Is_specialization_v<_Uty, expected>, + "expected::or_else(F) requires the return type of F to be a specialization of expected " + "N4928 [expected.object.monadic]/11."); + static_assert(is_same_v, + "expected::or_else(F) requires the value type of the return type of F to be T" + "N4928 [expected.object.monadic]/11."); + + if (this->_Has_value) { + return _Uty(in_place, _STD move(this->_Value)); + } else { + return _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Unexpected)); + } + } + + template + requires is_move_constructible_v<_Err> + constexpr auto transform(_Fn&& _Func) & { + using _Uty = remove_cv_t>; + + if (this->_Has_value) { + if constexpr (is_void_v<_Uty>) { + _STD invoke(_STD forward<_Fn>(_Func), this->_Value); + return expected<_Uty, _Err>(); + } else { + return expected<_Uty, _Err>( + _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), this->_Value); + } + } else { + return expected<_Uty, _Err>(unexpect, this->_Unexpected); + } + } + + template + requires is_copy_constructible_v<_Err> + constexpr auto transform(_Fn&& _Func) const& { + using _Uty = remove_cv_t>; + + if (this->_Has_value) { + if constexpr (is_void_v<_Uty>) { + _STD invoke(_STD forward<_Fn>(_Func), this->_Value); + return expected<_Uty, _Err>(); + } else { + return expected<_Uty, _Err>( + _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), this->_Value); + } + } else { + return expected<_Uty, _Err>(unexpect, this->_Unexpected); + } + } + + + template + requires is_move_constructible_v<_Err> + constexpr auto transform(_Fn&& _Func) && { + using _Uty = remove_cv_t>; + + if (this->_Has_value) { + if constexpr (is_void_v<_Uty>) { + _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Value)); + return expected<_Uty, _Err>(); + } else { + return expected<_Uty, _Err>( + _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _STD move(this->_Value)); + } + } else { + return expected<_Uty, _Err>(unexpect, _STD move(this->_Unexpected)); + } + } + + template + requires is_move_constructible_v<_Err> + constexpr auto transform(_Fn&& _Func) const&& { + using _Uty = remove_cv_t>; + + if (this->_Has_value) { + if constexpr (is_void_v<_Uty>) { + _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Value)); + return expected<_Uty, _Err>(); + } else { + return expected<_Uty, _Err>( + _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _STD move(this->_Value)); + } + } else { + return expected<_Uty, _Err>(unexpect, _STD move(this->_Unexpected)); + } + } + + template + requires is_copy_constructible_v<_Ty> + constexpr auto transform_error(_Fn&& _Func) & { + using _Uty = remove_cv_t>; + + if (this->_Has_value) { + return expected<_Ty, _Uty>(in_place, this->_Value); + } else { + return expected<_Ty, _Uty>( + _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), this->_Unexpected); + } + } + + template + requires is_copy_constructible_v<_Ty> + constexpr auto transform_error(_Fn&& _Func) const& { + using _Uty = remove_cv_t>; + + if (this->_Has_value) { + return expected<_Ty, _Uty>(in_place, this->_Value); + } else { + return expected<_Ty, _Uty>( + _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), this->_Unexpected); + } + } + + template + requires is_move_constructible_v<_Ty> + constexpr auto transform_error(_Fn&& _Func) && { + using _Uty = remove_cv_t>; + + if (this->_Has_value) { + return expected<_Ty, _Uty>(in_place, _STD move(this->_Value)); + } else { + return expected<_Ty, _Uty>(_Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), + _STD move(this->_Unexpected)); + } + } + + template + requires is_move_constructible_v<_Ty> + constexpr auto transform_error(_Fn&& _Func) const&& { + using _Uty = remove_cv_t>; + + if (this->_Has_value) { + return expected<_Ty, _Uty>(in_place, _STD move(this->_Value)); + } else { + return expected<_Ty, _Uty>(_Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), + _STD move(this->_Unexpected)); + } + } + // [expected.object.eq] template @@ -722,6 +1023,24 @@ public: } private: + // These overloads force copy elision from the invoke call into _Value + template + constexpr expected(_Construct_expected_from_invoke_result_tag, _Fn&& _Func, _Ux&& _Arg) noexcept( + is_nothrow_constructible_v<_Ty, invoke_result_t<_Fn, _Ux>>) + : _Value(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))), _Has_value{true} {} + + // For when transform is called on an expected + template + constexpr expected(_Construct_expected_from_invoke_result_tag, _Fn&& _Func) noexcept( + is_nothrow_constructible_v<_Ty, invoke_result_t<_Fn>>) + : _Value(_STD invoke(_STD forward<_Fn>(_Func))), _Has_value{true} {} + + template + constexpr expected(_Construct_expected_from_invoke_result_tag, unexpect_t, _Fn&& _Func, _Ux&& _Arg) noexcept( + is_nothrow_constructible_v<_Err, invoke_result_t<_Fn, _Ux>>) + : _Unexpected(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))), _Has_value{false} {} + + [[noreturn]] void _Throw_bad_expected_access_lv() const { _THROW(bad_expected_access{_Unexpected}); } @@ -1033,6 +1352,295 @@ public: return _STD move(_Unexpected); } + template + _NODISCARD constexpr _Err error_or(_Uty&& _Other) const& noexcept( + is_nothrow_copy_constructible_v<_Err>&& is_nothrow_convertible_v<_Uty, _Err>) { // strengthened + static_assert( + is_copy_constructible_v<_Err>, "is_copy_constructible_v must be true. (N4928 [expected.object.obs]/20)"); + static_assert( + is_convertible_v<_Uty, _Err>, "is_convertible_v must be true. (N4928 [expected.object.obs]/20)"); + + if (_Has_value) { + return _STD forward<_Uty>(_Other); + } else { + return _Unexpected; + } + } + + template + _NODISCARD constexpr _Err error_or(_Uty&& _Other) && noexcept( + is_nothrow_move_constructible_v<_Err>&& is_nothrow_convertible_v<_Uty, _Err>) { // strengthened + static_assert( + is_move_constructible_v<_Err>, "is_move_constructible_v must be true. (N4928 [expected.object.obs]/22)"); + static_assert( + is_convertible_v<_Uty, _Err>, "is_convertible_v must be true. (N4928 [expected.object.obs]/22)"); + + if (_Has_value) { + return _STD forward<_Uty>(_Other); + } else { + return _STD move(_Unexpected); + } + } + + // [expected.object.monadic] + + template + requires is_copy_constructible_v<_Err> + constexpr auto and_then(_Fn&& _Func) & { + using _Uty = remove_cvref_t>; + + static_assert(_Is_specialization_v<_Uty, expected>, + "expected::and_then(F) requires the return type of F to be a specialization of expected " + "N4928 [expected.object.monadic]/3."); + + if (this->_Has_value) { + return _STD invoke(_STD forward<_Fn>(_Func)); + } else { + return _Uty(unexpect, this->_Unexpected); + } + } + + template + requires is_copy_constructible_v<_Err> + constexpr auto and_then(_Fn&& _Func) const& { + using _Uty = remove_cvref_t>; + + static_assert(_Is_specialization_v<_Uty, expected>, + "expected::and_then(F) requires the return type of F to be a specialization of expected " + "N4928 [expected.object.monadic]/3."); + + if (this->_Has_value) { + return _STD invoke(_STD forward<_Fn>(_Func)); + } else { + return _Uty(unexpect, this->_Unexpected); + } + } + + template + requires is_move_constructible_v<_Err> + constexpr auto and_then(_Fn&& _Func) && { + using _Uty = remove_cvref_t>; + + static_assert(_Is_specialization_v<_Uty, expected>, + "expected::and_then(F) requires the return type of F to be a specialization of expected " + "N4928 [expected.object.monadic]/7."); + + if (this->_Has_value) { + return _STD invoke(_STD forward<_Fn>(_Func)); + } else { + return _Uty(unexpect, _STD move(this->_Unexpected)); + } + } + + template + requires is_move_constructible_v<_Err> + constexpr auto and_then(_Fn&& _Func) const&& { + using _Uty = remove_cvref_t>; + + static_assert(_Is_specialization_v<_Uty, expected>, + "expected::and_then(F) requires the return type of F to be a specialization of optional " + "N4928 [expected.object.monadic]/7."); + + if (this->_Has_value) { + return _STD invoke(_STD forward<_Fn>(_Func)); + } else { + return _Uty(unexpect, _STD move(this->_Unexpected)); + } + } + + template + constexpr auto or_else(_Fn&& _Func) & { + using _Uty = remove_cvref_t>; + + static_assert(_Is_specialization_v<_Uty, expected>, + "expected::or_else(F) requires the return type of F to be a specialization of expected " + "N4928 [expected.object.monadic]/11."); + static_assert(is_same_v, + "expected::or_else(F) requires the value type of the return type of F to be T" + "N4928 [expected.object.monadic]/11."); + + if (this->_Has_value) { + return _Uty(); + } else { + return _STD invoke(_STD forward<_Fn>(_Func), this->_Unexpected); + } + } + + template + constexpr auto or_else(_Fn&& _Func) const& { + using _Uty = remove_cvref_t>; + + static_assert(_Is_specialization_v<_Uty, expected>, + "expected::or_else(F) requires the return type of F to be a specialization of expected " + "N4928 [expected.object.monadic]/11."); + static_assert(is_same_v, + "expected::or_else(F) requires the value type of the return type of F to be T" + "N4928 [expected.object.monadic]/11."); + + if (this->_Has_value) { + return _Uty(); + } else { + return _STD invoke(_STD forward<_Fn>(_Func), this->_Unexpected); + } + } + + template + constexpr auto or_else(_Fn&& _Func) && { + using _Uty = remove_cvref_t>; + + static_assert(_Is_specialization_v<_Uty, expected>, + "expected::or_else(F) requires the return type of F to be a specialization of expected " + "N4928 [expected.object.monadic]/11."); + static_assert(is_same_v, + "expected::or_else(F) requires the value type of the return type of F to be T" + "N4928 [expected.object.monadic]/11."); + + if (this->_Has_value) { + return _Uty(); + } else { + return _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Unexpected)); + } + } + + template + constexpr auto or_else(_Fn&& _Func) const&& { + using _Uty = remove_cvref_t>; + + static_assert(_Is_specialization_v<_Uty, expected>, + "expected::or_else(F) requires the return type of F to be a specialization of expected " + "N4928 [expected.object.monadic]/11."); + static_assert(is_same_v, + "expected::or_else(F) requires the value type of the return type of F to be T" + "N4928 [expected.object.monadic]/11."); + + if (this->_Has_value) { + return _Uty(); + } else { + return _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Unexpected)); + } + } + + template + requires is_move_constructible_v<_Err> + constexpr auto transform(_Fn&& _Func) & { + using _Uty = remove_cv_t>; + + if (this->_Has_value) { + if constexpr (is_void_v<_Uty>) { + _STD invoke(_STD forward<_Fn>(_Func)); + return expected<_Uty, _Err>(); + } else { + return expected<_Uty, _Err>( + _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); + } + } else { + return expected<_Uty, _Err>(unexpect, this->_Unexpected); + } + } + + template + requires is_copy_constructible_v<_Err> + constexpr auto transform(_Fn&& _Func) const& { + using _Uty = remove_cv_t>; + + if (this->_Has_value) { + if constexpr (is_void_v<_Uty>) { + _STD invoke(_STD forward<_Fn>(_Func)); + return expected<_Uty, _Err>(); + } else { + return expected<_Uty, _Err>( + _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); + } + } else { + return expected<_Uty, _Err>(unexpect, this->_Unexpected); + } + } + + + template + requires is_move_constructible_v<_Err> + constexpr auto transform(_Fn&& _Func) && { + using _Uty = remove_cv_t>; + + if (this->_Has_value) { + if constexpr (is_void_v<_Uty>) { + _STD invoke(_STD forward<_Fn>(_Func)); + return expected<_Uty, _Err>(); + } else { + return expected<_Uty, _Err>( + _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); + } + } else { + return expected<_Uty, _Err>(unexpect, _STD move(this->_Unexpected)); + } + } + + template + requires is_move_constructible_v<_Err> + constexpr auto transform(_Fn&& _Func) const&& { + using _Uty = remove_cv_t>; + + if (this->_Has_value) { + if constexpr (is_void_v<_Uty>) { + _STD invoke(_STD forward<_Fn>(_Func)); + return expected<_Uty, _Err>(); + } else { + return expected<_Uty, _Err>( + _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); + } + } else { + return expected<_Uty, _Err>(unexpect, _STD move(this->_Unexpected)); + } + } + + template + constexpr auto transform_error(_Fn&& _Func) & { + using _Uty = remove_cv_t>; + + if (this->_Has_value) { + return expected<_Ty, _Uty>(); + } else { + return expected<_Ty, _Uty>( + _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), this->_Unexpected); + } + } + + template + constexpr auto transform_error(_Fn&& _Func) const& { + using _Uty = remove_cv_t>; + + if (this->_Has_value) { + return expected<_Ty, _Uty>(); + } else { + return expected<_Ty, _Uty>( + _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), this->_Unexpected); + } + } + + template + constexpr auto transform_error(_Fn&& _Func) && { + using _Uty = remove_cv_t>; + + if (this->_Has_value) { + return expected<_Ty, _Uty>(); + } else { + return expected<_Ty, _Uty>(_Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), + _STD move(this->_Unexpected)); + } + } + + template + constexpr auto transform_error(_Fn&& _Func) const&& { + using _Uty = remove_cv_t>; + + if (this->_Has_value) { + return expected<_Ty, _Uty>(); + } else { + return expected<_Ty, _Uty>(_Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), + _STD move(this->_Unexpected)); + } + } + // [expected.void.eq] template requires is_void_v<_Uty> @@ -1056,6 +1664,11 @@ public: } private: + template + constexpr expected(_Construct_expected_from_invoke_result_tag, unexpect_t, _Fn&& _Func, _Ux&& _Arg) noexcept( + is_nothrow_constructible_v<_Err, invoke_result_t<_Fn, _Ux>>) + : _Unexpected(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))), _Has_value{false} {} + [[noreturn]] void _Throw_bad_expected_access_lv() const { _THROW(bad_expected_access{_Unexpected}); } diff --git a/tests/std/tests/P2505R5_monadic_functions_for_expected/env.lst b/tests/std/tests/P2505R5_monadic_functions_for_expected/env.lst new file mode 100644 index 00000000000..8ac7033b206 --- /dev/null +++ b/tests/std/tests/P2505R5_monadic_functions_for_expected/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\strict_concepts_latest_matrix.lst diff --git a/tests/std/tests/P2505R5_monadic_functions_for_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_expected/test.cpp new file mode 100644 index 00000000000..299007158ff --- /dev/null +++ b/tests/std/tests/P2505R5_monadic_functions_for_expected/test.cpp @@ -0,0 +1,332 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include + +using namespace std; + +enum class IsNothrowConstructible : bool { Not, Yes }; +enum class IsNothrowConvertible : bool { Not, Yes }; + +template +[[nodiscard]] constexpr bool IsYes(const E e) noexcept { + return e == E::Yes; +} + +struct convertible { + constexpr convertible() = default; + constexpr convertible(const int val) noexcept : _val(val) {} + + [[nodiscard]] constexpr bool operator==(const int other) const noexcept { + return other == _val; + } + + int _val = 0; +}; + +struct Immovable { + constexpr Immovable(int x) : v(x) {} + Immovable(const Immovable&) = delete; + Immovable(Immovable&&) = delete; + Immovable& operator=(const Immovable&) = delete; + Immovable& operator=(Immovable&&) = delete; + constexpr ~Immovable() {} + + int v; +}; + +struct Thingy { + expected x; + constexpr int member_func() const { + return 66; + } +}; + +template +constexpr void test_impl(Expected&& exp, Expected&& unexp) { + assert(exp.has_value()); + assert(!unexp.has_value()); + using Val = typename remove_cvref_t::value_type; + + auto succeed = [](auto...) { return expected{33}; }; + auto fail = [](auto...) { return expected(unexpect, 44); }; + + { + decltype(auto) result = forward(exp).and_then(succeed); + static_assert(is_same_v>); + assert(result == 33); + } + { + decltype(auto) result = forward(unexp).and_then(succeed); + static_assert(is_same_v>); + assert(!result); + assert(result.error() == 22); + } + { + decltype(auto) result = forward(exp).and_then(fail); + static_assert(is_same_v>); + assert(!result); + assert(result.error() == 44); + } + { + decltype(auto) result = forward(unexp).and_then(fail); + static_assert(is_same_v>); + assert(!result); + assert(result.error() == 22); + } + if constexpr (!is_void_v) { + { + decltype(auto) result = forward(exp).and_then(&Thingy::x); + static_assert(is_same_v>); + assert(result == 11); + } + { + decltype(auto) result = forward(unexp).and_then(&Thingy::x); + static_assert(is_same_v>); + assert(result.error() == 22); + } + } + + auto f = [](auto...) { return 55; }; + auto immov = [](auto...) { return Immovable{88}; }; + auto to_void = [](auto...) { return; }; + + { + decltype(auto) result = forward(exp).transform(f); + static_assert(is_same_v>); + assert(result == 55); + } + { + decltype(auto) result = forward(unexp).transform(f); + static_assert(is_same_v>); + assert(!result); + assert(result.error() == 22); + } + if constexpr (!is_void_v) { + { + decltype(auto) result = forward(exp).transform(&Thingy::member_func); + static_assert(is_same_v>); + assert(result == 66); + } + { + decltype(auto) result = forward(unexp).transform(&Thingy::member_func); + static_assert(is_same_v>); + assert(result.error() == 22); + } + } + { + decltype(auto) result = forward(exp).transform(immov); + static_assert(is_same_v>); + assert(result->v == 88); + } + { + decltype(auto) result = forward(unexp).transform(immov); + static_assert(is_same_v>); + assert(!result); + assert(result.error() == 22); + } + { + decltype(auto) result = forward(exp).transform(to_void); + static_assert(is_same_v>); + assert(result); + } + { + decltype(auto) result = forward(unexp).transform(to_void); + static_assert(is_same_v>); + assert(!result); + assert(result.error() == 22); + } + + + auto to_thingy = [](int i) { return Thingy{i}; }; + + { + decltype(auto) result = forward(exp).transform_error(to_thingy); + static_assert(is_same_v>); + assert(result); + if constexpr (!is_void_v) { + assert(result->x == 11); + } + } + { + decltype(auto) result = forward(unexp).transform_error(to_thingy); + static_assert(is_same_v>); + assert(!result); + assert(result.error().x == 22); + } + { + decltype(auto) result = forward(exp).transform_error(to_thingy).transform_error(&Thingy::member_func); + static_assert(is_same_v>); + if constexpr (!is_void_v) { + assert(result->x == 11); + } + } + { + decltype(auto) result = + forward(unexp).transform_error(to_thingy).transform_error(&Thingy::member_func); + static_assert(is_same_v>); + assert(!result); + assert(result.error() == 66); + } + { + decltype(auto) result = forward(exp).transform_error(immov); + static_assert(is_same_v>); + if constexpr (!is_void_v) { + assert(result->x == 11); + } + } + { + decltype(auto) result = forward(unexp).transform_error(immov); + static_assert(is_same_v>); + assert(!result); + assert(result.error().v == 88); + } + + auto to_expected_thingy = [](auto...) { + if constexpr (is_void_v) { + return expected{}; + } else { + return expected{Thingy{77}}; + } + }; + { + decltype(auto) result = forward(exp).or_else(to_expected_thingy); + static_assert(is_same_v>); + assert(result); + if constexpr (!is_void_v) { + assert(result.value().x == 11); + } + } + { + decltype(auto) result = forward(unexp).or_else(to_expected_thingy); + static_assert(is_same_v>); + assert(result); + if constexpr (!is_void_v) { + assert(result.value().x == 77); + } + } +} + +template +constexpr void test_error_or() { + constexpr bool construction_is_noexcept = IsYes(nothrowConstructible); + constexpr bool conversion_is_noexcept = IsYes(nothrowConvertible); + constexpr bool should_be_noexcept = construction_is_noexcept && conversion_is_noexcept; + + struct payload_error_or { + constexpr payload_error_or(const int val) noexcept : _val(val) {} + constexpr payload_error_or(const payload_error_or& other) noexcept(construction_is_noexcept) + : _val(other._val + 2) {} + constexpr payload_error_or(payload_error_or&& other) noexcept(construction_is_noexcept) + : _val(other._val + 3) {} + constexpr payload_error_or(const convertible& val) noexcept(conversion_is_noexcept) : _val(val._val + 4) {} + constexpr payload_error_or(convertible&& val) noexcept(conversion_is_noexcept) : _val(val._val + 5) {} + + [[nodiscard]] constexpr bool operator==(const payload_error_or& right) const noexcept { + return _val == right._val; + } + + int _val = 0; + }; + + { // with payload argument + using Expected = expected; + + Expected with_error{unexpect, 42}; + const Expected const_with_error{unexpect, 1337}; + assert(with_error.error_or(payload_error_or{1}) == 42 + 2); + assert(const_with_error.error_or(payload_error_or{1}) == 1337 + 2); + static_assert(noexcept(with_error.error_or(payload_error_or{1})) == construction_is_noexcept); + static_assert(noexcept(const_with_error.error_or(payload_error_or{1})) == construction_is_noexcept); + + assert(move(with_error).error_or(payload_error_or{1}) == 42 + 3); + assert(move(const_with_error).error_or(payload_error_or{1}) == 1337 + 2); + static_assert(noexcept(move(with_error).error_or(payload_error_or{1})) == construction_is_noexcept); + static_assert(noexcept(move(const_with_error).error_or(payload_error_or{1})) == construction_is_noexcept); + + const payload_error_or input{2}; + Expected with_value{in_place, 42}; + const Expected const_with_value{in_place, 1337}; + assert(with_value.error_or(payload_error_or{1}) == 1 + 3); + assert(const_with_value.error_or(input) == 2 + 2); + static_assert(noexcept(with_value.error_or(payload_error_or{1})) == construction_is_noexcept); + static_assert(noexcept(const_with_value.error_or(input)) == construction_is_noexcept); + + assert(move(with_value).error_or(payload_error_or{1}) == 1 + 3); + assert(move(const_with_value).error_or(input) == 2 + 2); + static_assert(noexcept(move(with_value).error_or(payload_error_or{1})) == construction_is_noexcept); + static_assert(noexcept(move(const_with_value).error_or(input)) == construction_is_noexcept); + } + + { // with convertible argument + using Expected = expected; + + Expected with_error{unexpect, 42}; + const Expected const_with_error{unexpect, 1337}; + assert(with_error.error_or(convertible{1}) == 42 + 2); + assert(const_with_error.error_or(convertible{1}) == 1337 + 2); + static_assert(noexcept(with_error.error_or(convertible{1})) == should_be_noexcept); + static_assert(noexcept(const_with_error.error_or(convertible{1})) == should_be_noexcept); + + assert(move(with_error).error_or(convertible{1}) == 42 + 3); + assert(move(const_with_error).error_or(convertible{1}) == 1337 + 2); + static_assert(noexcept(move(with_error).error_or(convertible{1})) == should_be_noexcept); + static_assert(noexcept(move(const_with_error).error_or(convertible{1})) == should_be_noexcept); + + const convertible input{2}; + Expected with_value{in_place, 42}; + const Expected const_with_value{in_place, 1337}; + assert(with_value.error_or(convertible{1}) == 1 + 5); + assert(const_with_value.error_or(input) == 2 + 4); + static_assert(noexcept(with_value.error_or(convertible{1})) == should_be_noexcept); + static_assert(noexcept(const_with_value.error_or(input)) == should_be_noexcept); + + assert(move(with_value).error_or(convertible{1}) == 1 + 5); + assert(move(const_with_value).error_or(input) == 2 + 4); + static_assert(noexcept(move(with_value).error_or(convertible{1})) == should_be_noexcept); + static_assert(noexcept(move(const_with_value).error_or(input)) == should_be_noexcept); + } +} + +constexpr void test_error_or() noexcept { + test_error_or(); + test_error_or(); + test_error_or(); + test_error_or(); +} + +constexpr void test_monadic() { + { + expected exp{Thingy{11}}; + expected unexp{std::unexpect, 22}; + test_impl(exp, unexp); + test_impl(as_const(exp), as_const(unexp)); + test_impl(move(exp), move(unexp)); + test_impl(move(as_const(exp)), move(as_const(unexp))); + } + + { + expected exp{}; + expected unexp{std::unexpect, 22}; + test_impl(exp, unexp); + test_impl(as_const(exp), as_const(unexp)); + test_impl(move(exp), move(unexp)); + test_impl(move(as_const(exp)), move(as_const(unexp))); + } +} + + +constexpr bool test() { + test_error_or(); + test_monadic(); + + return true; +} + +int main() { + test(); + // static_assert(test()); +} From 30d84179fb2f534644e21b2b4583cbd918d09dc2 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Wed, 25 Jan 2023 14:12:15 +0000 Subject: [PATCH 02/50] Clang format --- stl/inc/expected | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index 5674bfadf00..c8a87dd49c2 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -1530,8 +1530,7 @@ public: _STD invoke(_STD forward<_Fn>(_Func)); return expected<_Uty, _Err>(); } else { - return expected<_Uty, _Err>( - _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); + return expected<_Uty, _Err>(_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); } } else { return expected<_Uty, _Err>(unexpect, this->_Unexpected); @@ -1548,8 +1547,7 @@ public: _STD invoke(_STD forward<_Fn>(_Func)); return expected<_Uty, _Err>(); } else { - return expected<_Uty, _Err>( - _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); + return expected<_Uty, _Err>(_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); } } else { return expected<_Uty, _Err>(unexpect, this->_Unexpected); @@ -1567,8 +1565,7 @@ public: _STD invoke(_STD forward<_Fn>(_Func)); return expected<_Uty, _Err>(); } else { - return expected<_Uty, _Err>( - _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); + return expected<_Uty, _Err>(_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); } } else { return expected<_Uty, _Err>(unexpect, _STD move(this->_Unexpected)); @@ -1585,8 +1582,7 @@ public: _STD invoke(_STD forward<_Fn>(_Func)); return expected<_Uty, _Err>(); } else { - return expected<_Uty, _Err>( - _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); + return expected<_Uty, _Err>(_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); } } else { return expected<_Uty, _Err>(unexpect, _STD move(this->_Unexpected)); From d70650ec5fa1b2e8310677f1f376edc3b3c65d9a Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Wed, 25 Jan 2023 14:21:04 +0000 Subject: [PATCH 03/50] Correct type traits --- stl/inc/expected | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index c8a87dd49c2..ca4a18416ea 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -862,7 +862,7 @@ public: } template - requires is_move_constructible_v<_Err> + requires is_copy_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) & { using _Uty = remove_cv_t>; @@ -1521,7 +1521,7 @@ public: } template - requires is_move_constructible_v<_Err> + requires is_copy_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) & { using _Uty = remove_cv_t>; From 5429deadbcc06d21f3db38f993955614336dd283 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Wed, 25 Jan 2023 14:21:42 +0000 Subject: [PATCH 04/50] Fix copy paste errors --- stl/inc/expected | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index ca4a18416ea..6a1ac3565e2 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -775,7 +775,7 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of optional " + "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.object.monadic]/7."); if (this->_Has_value) { @@ -1438,7 +1438,7 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of optional " + "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.object.monadic]/7."); if (this->_Has_value) { From fb3af744e258ea88e83adce831794939f3cd80d0 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Wed, 25 Jan 2023 14:23:41 +0000 Subject: [PATCH 05/50] Test constexpr --- tests/std/tests/P2505R5_monadic_functions_for_expected/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P2505R5_monadic_functions_for_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_expected/test.cpp index 299007158ff..ca902ce28c1 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_expected/test.cpp @@ -328,5 +328,5 @@ constexpr bool test() { int main() { test(); - // static_assert(test()); + static_assert(test()); } From 1bb9f01076cbff69a76c2d26e2511e72051cab1d Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Wed, 25 Jan 2023 14:42:55 +0000 Subject: [PATCH 06/50] Update test paths --- .../env.lst | 4 - .../test.cpp | 332 ------------------ 2 files changed, 336 deletions(-) delete mode 100644 tests/std/tests/P2505R5_monadic_functions_for_expected/env.lst delete mode 100644 tests/std/tests/P2505R5_monadic_functions_for_expected/test.cpp diff --git a/tests/std/tests/P2505R5_monadic_functions_for_expected/env.lst b/tests/std/tests/P2505R5_monadic_functions_for_expected/env.lst deleted file mode 100644 index 8ac7033b206..00000000000 --- a/tests/std/tests/P2505R5_monadic_functions_for_expected/env.lst +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -RUNALL_INCLUDE ..\strict_concepts_latest_matrix.lst diff --git a/tests/std/tests/P2505R5_monadic_functions_for_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_expected/test.cpp deleted file mode 100644 index ca902ce28c1..00000000000 --- a/tests/std/tests/P2505R5_monadic_functions_for_expected/test.cpp +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#include -#include -#include -#include - -using namespace std; - -enum class IsNothrowConstructible : bool { Not, Yes }; -enum class IsNothrowConvertible : bool { Not, Yes }; - -template -[[nodiscard]] constexpr bool IsYes(const E e) noexcept { - return e == E::Yes; -} - -struct convertible { - constexpr convertible() = default; - constexpr convertible(const int val) noexcept : _val(val) {} - - [[nodiscard]] constexpr bool operator==(const int other) const noexcept { - return other == _val; - } - - int _val = 0; -}; - -struct Immovable { - constexpr Immovable(int x) : v(x) {} - Immovable(const Immovable&) = delete; - Immovable(Immovable&&) = delete; - Immovable& operator=(const Immovable&) = delete; - Immovable& operator=(Immovable&&) = delete; - constexpr ~Immovable() {} - - int v; -}; - -struct Thingy { - expected x; - constexpr int member_func() const { - return 66; - } -}; - -template -constexpr void test_impl(Expected&& exp, Expected&& unexp) { - assert(exp.has_value()); - assert(!unexp.has_value()); - using Val = typename remove_cvref_t::value_type; - - auto succeed = [](auto...) { return expected{33}; }; - auto fail = [](auto...) { return expected(unexpect, 44); }; - - { - decltype(auto) result = forward(exp).and_then(succeed); - static_assert(is_same_v>); - assert(result == 33); - } - { - decltype(auto) result = forward(unexp).and_then(succeed); - static_assert(is_same_v>); - assert(!result); - assert(result.error() == 22); - } - { - decltype(auto) result = forward(exp).and_then(fail); - static_assert(is_same_v>); - assert(!result); - assert(result.error() == 44); - } - { - decltype(auto) result = forward(unexp).and_then(fail); - static_assert(is_same_v>); - assert(!result); - assert(result.error() == 22); - } - if constexpr (!is_void_v) { - { - decltype(auto) result = forward(exp).and_then(&Thingy::x); - static_assert(is_same_v>); - assert(result == 11); - } - { - decltype(auto) result = forward(unexp).and_then(&Thingy::x); - static_assert(is_same_v>); - assert(result.error() == 22); - } - } - - auto f = [](auto...) { return 55; }; - auto immov = [](auto...) { return Immovable{88}; }; - auto to_void = [](auto...) { return; }; - - { - decltype(auto) result = forward(exp).transform(f); - static_assert(is_same_v>); - assert(result == 55); - } - { - decltype(auto) result = forward(unexp).transform(f); - static_assert(is_same_v>); - assert(!result); - assert(result.error() == 22); - } - if constexpr (!is_void_v) { - { - decltype(auto) result = forward(exp).transform(&Thingy::member_func); - static_assert(is_same_v>); - assert(result == 66); - } - { - decltype(auto) result = forward(unexp).transform(&Thingy::member_func); - static_assert(is_same_v>); - assert(result.error() == 22); - } - } - { - decltype(auto) result = forward(exp).transform(immov); - static_assert(is_same_v>); - assert(result->v == 88); - } - { - decltype(auto) result = forward(unexp).transform(immov); - static_assert(is_same_v>); - assert(!result); - assert(result.error() == 22); - } - { - decltype(auto) result = forward(exp).transform(to_void); - static_assert(is_same_v>); - assert(result); - } - { - decltype(auto) result = forward(unexp).transform(to_void); - static_assert(is_same_v>); - assert(!result); - assert(result.error() == 22); - } - - - auto to_thingy = [](int i) { return Thingy{i}; }; - - { - decltype(auto) result = forward(exp).transform_error(to_thingy); - static_assert(is_same_v>); - assert(result); - if constexpr (!is_void_v) { - assert(result->x == 11); - } - } - { - decltype(auto) result = forward(unexp).transform_error(to_thingy); - static_assert(is_same_v>); - assert(!result); - assert(result.error().x == 22); - } - { - decltype(auto) result = forward(exp).transform_error(to_thingy).transform_error(&Thingy::member_func); - static_assert(is_same_v>); - if constexpr (!is_void_v) { - assert(result->x == 11); - } - } - { - decltype(auto) result = - forward(unexp).transform_error(to_thingy).transform_error(&Thingy::member_func); - static_assert(is_same_v>); - assert(!result); - assert(result.error() == 66); - } - { - decltype(auto) result = forward(exp).transform_error(immov); - static_assert(is_same_v>); - if constexpr (!is_void_v) { - assert(result->x == 11); - } - } - { - decltype(auto) result = forward(unexp).transform_error(immov); - static_assert(is_same_v>); - assert(!result); - assert(result.error().v == 88); - } - - auto to_expected_thingy = [](auto...) { - if constexpr (is_void_v) { - return expected{}; - } else { - return expected{Thingy{77}}; - } - }; - { - decltype(auto) result = forward(exp).or_else(to_expected_thingy); - static_assert(is_same_v>); - assert(result); - if constexpr (!is_void_v) { - assert(result.value().x == 11); - } - } - { - decltype(auto) result = forward(unexp).or_else(to_expected_thingy); - static_assert(is_same_v>); - assert(result); - if constexpr (!is_void_v) { - assert(result.value().x == 77); - } - } -} - -template -constexpr void test_error_or() { - constexpr bool construction_is_noexcept = IsYes(nothrowConstructible); - constexpr bool conversion_is_noexcept = IsYes(nothrowConvertible); - constexpr bool should_be_noexcept = construction_is_noexcept && conversion_is_noexcept; - - struct payload_error_or { - constexpr payload_error_or(const int val) noexcept : _val(val) {} - constexpr payload_error_or(const payload_error_or& other) noexcept(construction_is_noexcept) - : _val(other._val + 2) {} - constexpr payload_error_or(payload_error_or&& other) noexcept(construction_is_noexcept) - : _val(other._val + 3) {} - constexpr payload_error_or(const convertible& val) noexcept(conversion_is_noexcept) : _val(val._val + 4) {} - constexpr payload_error_or(convertible&& val) noexcept(conversion_is_noexcept) : _val(val._val + 5) {} - - [[nodiscard]] constexpr bool operator==(const payload_error_or& right) const noexcept { - return _val == right._val; - } - - int _val = 0; - }; - - { // with payload argument - using Expected = expected; - - Expected with_error{unexpect, 42}; - const Expected const_with_error{unexpect, 1337}; - assert(with_error.error_or(payload_error_or{1}) == 42 + 2); - assert(const_with_error.error_or(payload_error_or{1}) == 1337 + 2); - static_assert(noexcept(with_error.error_or(payload_error_or{1})) == construction_is_noexcept); - static_assert(noexcept(const_with_error.error_or(payload_error_or{1})) == construction_is_noexcept); - - assert(move(with_error).error_or(payload_error_or{1}) == 42 + 3); - assert(move(const_with_error).error_or(payload_error_or{1}) == 1337 + 2); - static_assert(noexcept(move(with_error).error_or(payload_error_or{1})) == construction_is_noexcept); - static_assert(noexcept(move(const_with_error).error_or(payload_error_or{1})) == construction_is_noexcept); - - const payload_error_or input{2}; - Expected with_value{in_place, 42}; - const Expected const_with_value{in_place, 1337}; - assert(with_value.error_or(payload_error_or{1}) == 1 + 3); - assert(const_with_value.error_or(input) == 2 + 2); - static_assert(noexcept(with_value.error_or(payload_error_or{1})) == construction_is_noexcept); - static_assert(noexcept(const_with_value.error_or(input)) == construction_is_noexcept); - - assert(move(with_value).error_or(payload_error_or{1}) == 1 + 3); - assert(move(const_with_value).error_or(input) == 2 + 2); - static_assert(noexcept(move(with_value).error_or(payload_error_or{1})) == construction_is_noexcept); - static_assert(noexcept(move(const_with_value).error_or(input)) == construction_is_noexcept); - } - - { // with convertible argument - using Expected = expected; - - Expected with_error{unexpect, 42}; - const Expected const_with_error{unexpect, 1337}; - assert(with_error.error_or(convertible{1}) == 42 + 2); - assert(const_with_error.error_or(convertible{1}) == 1337 + 2); - static_assert(noexcept(with_error.error_or(convertible{1})) == should_be_noexcept); - static_assert(noexcept(const_with_error.error_or(convertible{1})) == should_be_noexcept); - - assert(move(with_error).error_or(convertible{1}) == 42 + 3); - assert(move(const_with_error).error_or(convertible{1}) == 1337 + 2); - static_assert(noexcept(move(with_error).error_or(convertible{1})) == should_be_noexcept); - static_assert(noexcept(move(const_with_error).error_or(convertible{1})) == should_be_noexcept); - - const convertible input{2}; - Expected with_value{in_place, 42}; - const Expected const_with_value{in_place, 1337}; - assert(with_value.error_or(convertible{1}) == 1 + 5); - assert(const_with_value.error_or(input) == 2 + 4); - static_assert(noexcept(with_value.error_or(convertible{1})) == should_be_noexcept); - static_assert(noexcept(const_with_value.error_or(input)) == should_be_noexcept); - - assert(move(with_value).error_or(convertible{1}) == 1 + 5); - assert(move(const_with_value).error_or(input) == 2 + 4); - static_assert(noexcept(move(with_value).error_or(convertible{1})) == should_be_noexcept); - static_assert(noexcept(move(const_with_value).error_or(input)) == should_be_noexcept); - } -} - -constexpr void test_error_or() noexcept { - test_error_or(); - test_error_or(); - test_error_or(); - test_error_or(); -} - -constexpr void test_monadic() { - { - expected exp{Thingy{11}}; - expected unexp{std::unexpect, 22}; - test_impl(exp, unexp); - test_impl(as_const(exp), as_const(unexp)); - test_impl(move(exp), move(unexp)); - test_impl(move(as_const(exp)), move(as_const(unexp))); - } - - { - expected exp{}; - expected unexp{std::unexpect, 22}; - test_impl(exp, unexp); - test_impl(as_const(exp), as_const(unexp)); - test_impl(move(exp), move(unexp)); - test_impl(move(as_const(exp)), move(as_const(unexp))); - } -} - - -constexpr bool test() { - test_error_or(); - test_monadic(); - - return true; -} - -int main() { - test(); - static_assert(test()); -} From 0bf5fc7397d7da2bfe97b666510898f291c38c69 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Wed, 25 Jan 2023 14:43:09 +0000 Subject: [PATCH 07/50] Update test paths --- .../env.lst | 4 + .../test.cpp | 332 ++++++++++++++++++ 2 files changed, 336 insertions(+) create mode 100644 tests/std/tests/P2505R5_monadic_functions_for_std_expected/env.lst create mode 100644 tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/env.lst b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/env.lst new file mode 100644 index 00000000000..8ac7033b206 --- /dev/null +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\strict_concepts_latest_matrix.lst diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp new file mode 100644 index 00000000000..ca902ce28c1 --- /dev/null +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -0,0 +1,332 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include + +using namespace std; + +enum class IsNothrowConstructible : bool { Not, Yes }; +enum class IsNothrowConvertible : bool { Not, Yes }; + +template +[[nodiscard]] constexpr bool IsYes(const E e) noexcept { + return e == E::Yes; +} + +struct convertible { + constexpr convertible() = default; + constexpr convertible(const int val) noexcept : _val(val) {} + + [[nodiscard]] constexpr bool operator==(const int other) const noexcept { + return other == _val; + } + + int _val = 0; +}; + +struct Immovable { + constexpr Immovable(int x) : v(x) {} + Immovable(const Immovable&) = delete; + Immovable(Immovable&&) = delete; + Immovable& operator=(const Immovable&) = delete; + Immovable& operator=(Immovable&&) = delete; + constexpr ~Immovable() {} + + int v; +}; + +struct Thingy { + expected x; + constexpr int member_func() const { + return 66; + } +}; + +template +constexpr void test_impl(Expected&& exp, Expected&& unexp) { + assert(exp.has_value()); + assert(!unexp.has_value()); + using Val = typename remove_cvref_t::value_type; + + auto succeed = [](auto...) { return expected{33}; }; + auto fail = [](auto...) { return expected(unexpect, 44); }; + + { + decltype(auto) result = forward(exp).and_then(succeed); + static_assert(is_same_v>); + assert(result == 33); + } + { + decltype(auto) result = forward(unexp).and_then(succeed); + static_assert(is_same_v>); + assert(!result); + assert(result.error() == 22); + } + { + decltype(auto) result = forward(exp).and_then(fail); + static_assert(is_same_v>); + assert(!result); + assert(result.error() == 44); + } + { + decltype(auto) result = forward(unexp).and_then(fail); + static_assert(is_same_v>); + assert(!result); + assert(result.error() == 22); + } + if constexpr (!is_void_v) { + { + decltype(auto) result = forward(exp).and_then(&Thingy::x); + static_assert(is_same_v>); + assert(result == 11); + } + { + decltype(auto) result = forward(unexp).and_then(&Thingy::x); + static_assert(is_same_v>); + assert(result.error() == 22); + } + } + + auto f = [](auto...) { return 55; }; + auto immov = [](auto...) { return Immovable{88}; }; + auto to_void = [](auto...) { return; }; + + { + decltype(auto) result = forward(exp).transform(f); + static_assert(is_same_v>); + assert(result == 55); + } + { + decltype(auto) result = forward(unexp).transform(f); + static_assert(is_same_v>); + assert(!result); + assert(result.error() == 22); + } + if constexpr (!is_void_v) { + { + decltype(auto) result = forward(exp).transform(&Thingy::member_func); + static_assert(is_same_v>); + assert(result == 66); + } + { + decltype(auto) result = forward(unexp).transform(&Thingy::member_func); + static_assert(is_same_v>); + assert(result.error() == 22); + } + } + { + decltype(auto) result = forward(exp).transform(immov); + static_assert(is_same_v>); + assert(result->v == 88); + } + { + decltype(auto) result = forward(unexp).transform(immov); + static_assert(is_same_v>); + assert(!result); + assert(result.error() == 22); + } + { + decltype(auto) result = forward(exp).transform(to_void); + static_assert(is_same_v>); + assert(result); + } + { + decltype(auto) result = forward(unexp).transform(to_void); + static_assert(is_same_v>); + assert(!result); + assert(result.error() == 22); + } + + + auto to_thingy = [](int i) { return Thingy{i}; }; + + { + decltype(auto) result = forward(exp).transform_error(to_thingy); + static_assert(is_same_v>); + assert(result); + if constexpr (!is_void_v) { + assert(result->x == 11); + } + } + { + decltype(auto) result = forward(unexp).transform_error(to_thingy); + static_assert(is_same_v>); + assert(!result); + assert(result.error().x == 22); + } + { + decltype(auto) result = forward(exp).transform_error(to_thingy).transform_error(&Thingy::member_func); + static_assert(is_same_v>); + if constexpr (!is_void_v) { + assert(result->x == 11); + } + } + { + decltype(auto) result = + forward(unexp).transform_error(to_thingy).transform_error(&Thingy::member_func); + static_assert(is_same_v>); + assert(!result); + assert(result.error() == 66); + } + { + decltype(auto) result = forward(exp).transform_error(immov); + static_assert(is_same_v>); + if constexpr (!is_void_v) { + assert(result->x == 11); + } + } + { + decltype(auto) result = forward(unexp).transform_error(immov); + static_assert(is_same_v>); + assert(!result); + assert(result.error().v == 88); + } + + auto to_expected_thingy = [](auto...) { + if constexpr (is_void_v) { + return expected{}; + } else { + return expected{Thingy{77}}; + } + }; + { + decltype(auto) result = forward(exp).or_else(to_expected_thingy); + static_assert(is_same_v>); + assert(result); + if constexpr (!is_void_v) { + assert(result.value().x == 11); + } + } + { + decltype(auto) result = forward(unexp).or_else(to_expected_thingy); + static_assert(is_same_v>); + assert(result); + if constexpr (!is_void_v) { + assert(result.value().x == 77); + } + } +} + +template +constexpr void test_error_or() { + constexpr bool construction_is_noexcept = IsYes(nothrowConstructible); + constexpr bool conversion_is_noexcept = IsYes(nothrowConvertible); + constexpr bool should_be_noexcept = construction_is_noexcept && conversion_is_noexcept; + + struct payload_error_or { + constexpr payload_error_or(const int val) noexcept : _val(val) {} + constexpr payload_error_or(const payload_error_or& other) noexcept(construction_is_noexcept) + : _val(other._val + 2) {} + constexpr payload_error_or(payload_error_or&& other) noexcept(construction_is_noexcept) + : _val(other._val + 3) {} + constexpr payload_error_or(const convertible& val) noexcept(conversion_is_noexcept) : _val(val._val + 4) {} + constexpr payload_error_or(convertible&& val) noexcept(conversion_is_noexcept) : _val(val._val + 5) {} + + [[nodiscard]] constexpr bool operator==(const payload_error_or& right) const noexcept { + return _val == right._val; + } + + int _val = 0; + }; + + { // with payload argument + using Expected = expected; + + Expected with_error{unexpect, 42}; + const Expected const_with_error{unexpect, 1337}; + assert(with_error.error_or(payload_error_or{1}) == 42 + 2); + assert(const_with_error.error_or(payload_error_or{1}) == 1337 + 2); + static_assert(noexcept(with_error.error_or(payload_error_or{1})) == construction_is_noexcept); + static_assert(noexcept(const_with_error.error_or(payload_error_or{1})) == construction_is_noexcept); + + assert(move(with_error).error_or(payload_error_or{1}) == 42 + 3); + assert(move(const_with_error).error_or(payload_error_or{1}) == 1337 + 2); + static_assert(noexcept(move(with_error).error_or(payload_error_or{1})) == construction_is_noexcept); + static_assert(noexcept(move(const_with_error).error_or(payload_error_or{1})) == construction_is_noexcept); + + const payload_error_or input{2}; + Expected with_value{in_place, 42}; + const Expected const_with_value{in_place, 1337}; + assert(with_value.error_or(payload_error_or{1}) == 1 + 3); + assert(const_with_value.error_or(input) == 2 + 2); + static_assert(noexcept(with_value.error_or(payload_error_or{1})) == construction_is_noexcept); + static_assert(noexcept(const_with_value.error_or(input)) == construction_is_noexcept); + + assert(move(with_value).error_or(payload_error_or{1}) == 1 + 3); + assert(move(const_with_value).error_or(input) == 2 + 2); + static_assert(noexcept(move(with_value).error_or(payload_error_or{1})) == construction_is_noexcept); + static_assert(noexcept(move(const_with_value).error_or(input)) == construction_is_noexcept); + } + + { // with convertible argument + using Expected = expected; + + Expected with_error{unexpect, 42}; + const Expected const_with_error{unexpect, 1337}; + assert(with_error.error_or(convertible{1}) == 42 + 2); + assert(const_with_error.error_or(convertible{1}) == 1337 + 2); + static_assert(noexcept(with_error.error_or(convertible{1})) == should_be_noexcept); + static_assert(noexcept(const_with_error.error_or(convertible{1})) == should_be_noexcept); + + assert(move(with_error).error_or(convertible{1}) == 42 + 3); + assert(move(const_with_error).error_or(convertible{1}) == 1337 + 2); + static_assert(noexcept(move(with_error).error_or(convertible{1})) == should_be_noexcept); + static_assert(noexcept(move(const_with_error).error_or(convertible{1})) == should_be_noexcept); + + const convertible input{2}; + Expected with_value{in_place, 42}; + const Expected const_with_value{in_place, 1337}; + assert(with_value.error_or(convertible{1}) == 1 + 5); + assert(const_with_value.error_or(input) == 2 + 4); + static_assert(noexcept(with_value.error_or(convertible{1})) == should_be_noexcept); + static_assert(noexcept(const_with_value.error_or(input)) == should_be_noexcept); + + assert(move(with_value).error_or(convertible{1}) == 1 + 5); + assert(move(const_with_value).error_or(input) == 2 + 4); + static_assert(noexcept(move(with_value).error_or(convertible{1})) == should_be_noexcept); + static_assert(noexcept(move(const_with_value).error_or(input)) == should_be_noexcept); + } +} + +constexpr void test_error_or() noexcept { + test_error_or(); + test_error_or(); + test_error_or(); + test_error_or(); +} + +constexpr void test_monadic() { + { + expected exp{Thingy{11}}; + expected unexp{std::unexpect, 22}; + test_impl(exp, unexp); + test_impl(as_const(exp), as_const(unexp)); + test_impl(move(exp), move(unexp)); + test_impl(move(as_const(exp)), move(as_const(unexp))); + } + + { + expected exp{}; + expected unexp{std::unexpect, 22}; + test_impl(exp, unexp); + test_impl(as_const(exp), as_const(unexp)); + test_impl(move(exp), move(unexp)); + test_impl(move(as_const(exp)), move(as_const(unexp))); + } +} + + +constexpr bool test() { + test_error_or(); + test_monadic(); + + return true; +} + +int main() { + test(); + static_assert(test()); +} From c859ed56770fa9f32b6c7826c5b22e02c254b845 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Wed, 25 Jan 2023 14:43:25 +0000 Subject: [PATCH 08/50] Feature test macro --- stl/inc/yvals_core.h | 3 ++- tests/std/test.lst | 1 + .../VSO_0157762_feature_test_macros/test.compile.pass.cpp | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 88cf2c26aeb..50cb2334263 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -345,6 +345,7 @@ // P2467R1 ios_base::noreplace: Exclusive Mode For fstreams // P2494R2 Relaxing Range Adaptors To Allow Move-Only Types // P2499R0 string_view Range Constructor Should Be explicit +// P2505R5 Monadic Functions For expected // P2549R1 unexpected::error() // P2602R2 Poison Pills Are Too Toxic @@ -1673,7 +1674,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #ifdef __cpp_lib_concepts #define __cpp_lib_containers_ranges 202202L -#define __cpp_lib_expected 202202L +#define __cpp_lib_expected 202211L #endif // __cpp_lib_concepts #define __cpp_lib_forward_like 202207L diff --git a/tests/std/test.lst b/tests/std/test.lst index 9652c56a554..7616b74172b 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -586,6 +586,7 @@ tests\P2446R2_views_as_rvalue tests\P2465R3_standard_library_modules tests\P2467R1_exclusive_mode_fstreams tests\P2494R2_move_only_range_adaptors +tests\P2505R5_monadic_functions_for_std_expected tests\P2517R1_apply_conditional_noexcept tests\VSO_0000000_allocator_propagation tests\VSO_0000000_any_calling_conventions diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index d2c679c1dc9..f0d29bbfacc 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -801,10 +801,10 @@ STATIC_ASSERT(__cpp_lib_execution == 201603L); #if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 #ifndef __cpp_lib_expected #error __cpp_lib_expected is not defined -#elif __cpp_lib_expected != 202202L -#error __cpp_lib_expected is not 202202L +#elif __cpp_lib_expected != 202211L +#error __cpp_lib_expected is not 202211L #else -STATIC_ASSERT(__cpp_lib_expected == 202202L); +STATIC_ASSERT(__cpp_lib_expected == 202211L); #endif #else #ifdef __cpp_lib_expected From 4757c75db1a8f049c39809cfc63d6e158e02005d Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Thu, 26 Jan 2023 09:08:56 +0000 Subject: [PATCH 09/50] Remove this-> --- stl/inc/expected | 168 +++++++++--------- .../env.lst | 2 +- 2 files changed, 85 insertions(+), 85 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index 6a1ac3565e2..742134afd8f 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -730,10 +730,10 @@ public: "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.object.monadic]/3."); - if (this->_Has_value) { - return _STD invoke(_STD forward<_Fn>(_Func), this->_Value); + if (_Has_value) { + return _STD invoke(_STD forward<_Fn>(_Func), _Value); } else { - return _Uty(unexpect, this->_Unexpected); + return _Uty(unexpect, _Unexpected); } } @@ -746,10 +746,10 @@ public: "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.object.monadic]/3."); - if (this->_Has_value) { - return _STD invoke(_STD forward<_Fn>(_Func), this->_Value); + if (_Has_value) { + return _STD invoke(_STD forward<_Fn>(_Func), _Value); } else { - return _Uty(unexpect, this->_Unexpected); + return _Uty(unexpect, _Unexpected); } } @@ -762,10 +762,10 @@ public: "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.object.monadic]/7."); - if (this->_Has_value) { - return _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Value)); + if (_Has_value) { + return _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Value)); } else { - return _Uty(unexpect, _STD move(this->_Unexpected)); + return _Uty(unexpect, _STD move(_Unexpected)); } } @@ -778,10 +778,10 @@ public: "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.object.monadic]/7."); - if (this->_Has_value) { - return _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Value)); + if (_Has_value) { + return _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Value)); } else { - return _Uty(unexpect, _STD move(this->_Unexpected)); + return _Uty(unexpect, _STD move(_Unexpected)); } } @@ -797,10 +797,10 @@ public: "expected::or_else(F) requires the value type of the return type of F to be T" "N4928 [expected.object.monadic]/11."); - if (this->_Has_value) { - return _Uty(in_place, this->_Value); + if (_Has_value) { + return _Uty(in_place, _Value); } else { - return _STD invoke(_STD forward<_Fn>(_Func), this->_Unexpected); + return _STD invoke(_STD forward<_Fn>(_Func), _Unexpected); } } @@ -816,10 +816,10 @@ public: "expected::or_else(F) requires the value type of the return type of F to be T" "N4928 [expected.object.monadic]/11."); - if (this->_Has_value) { - return _Uty(in_place, this->_Value); + if (_Has_value) { + return _Uty(in_place, _Value); } else { - return _STD invoke(_STD forward<_Fn>(_Func), this->_Unexpected); + return _STD invoke(_STD forward<_Fn>(_Func), _Unexpected); } } @@ -835,10 +835,10 @@ public: "expected::or_else(F) requires the value type of the return type of F to be T" "N4928 [expected.object.monadic]/11."); - if (this->_Has_value) { - return _Uty(in_place, _STD move(this->_Value)); + if (_Has_value) { + return _Uty(in_place, _STD move(_Value)); } else { - return _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Unexpected)); + return _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Unexpected)); } } @@ -854,10 +854,10 @@ public: "expected::or_else(F) requires the value type of the return type of F to be T" "N4928 [expected.object.monadic]/11."); - if (this->_Has_value) { - return _Uty(in_place, _STD move(this->_Value)); + if (_Has_value) { + return _Uty(in_place, _STD move(_Value)); } else { - return _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Unexpected)); + return _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Unexpected)); } } @@ -866,16 +866,16 @@ public: constexpr auto transform(_Fn&& _Func) & { using _Uty = remove_cv_t>; - if (this->_Has_value) { + if (_Has_value) { if constexpr (is_void_v<_Uty>) { - _STD invoke(_STD forward<_Fn>(_Func), this->_Value); + _STD invoke(_STD forward<_Fn>(_Func), _Value); return expected<_Uty, _Err>(); } else { return expected<_Uty, _Err>( - _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), this->_Value); + _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _Value); } } else { - return expected<_Uty, _Err>(unexpect, this->_Unexpected); + return expected<_Uty, _Err>(unexpect, _Unexpected); } } @@ -884,16 +884,16 @@ public: constexpr auto transform(_Fn&& _Func) const& { using _Uty = remove_cv_t>; - if (this->_Has_value) { + if (_Has_value) { if constexpr (is_void_v<_Uty>) { - _STD invoke(_STD forward<_Fn>(_Func), this->_Value); + _STD invoke(_STD forward<_Fn>(_Func), _Value); return expected<_Uty, _Err>(); } else { return expected<_Uty, _Err>( - _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), this->_Value); + _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _Value); } } else { - return expected<_Uty, _Err>(unexpect, this->_Unexpected); + return expected<_Uty, _Err>(unexpect, _Unexpected); } } @@ -903,16 +903,16 @@ public: constexpr auto transform(_Fn&& _Func) && { using _Uty = remove_cv_t>; - if (this->_Has_value) { + if (_Has_value) { if constexpr (is_void_v<_Uty>) { - _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Value)); + _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Value)); return expected<_Uty, _Err>(); } else { return expected<_Uty, _Err>( - _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _STD move(this->_Value)); + _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _STD move(_Value)); } } else { - return expected<_Uty, _Err>(unexpect, _STD move(this->_Unexpected)); + return expected<_Uty, _Err>(unexpect, _STD move(_Unexpected)); } } @@ -921,16 +921,16 @@ public: constexpr auto transform(_Fn&& _Func) const&& { using _Uty = remove_cv_t>; - if (this->_Has_value) { + if (_Has_value) { if constexpr (is_void_v<_Uty>) { - _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Value)); + _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Value)); return expected<_Uty, _Err>(); } else { return expected<_Uty, _Err>( - _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _STD move(this->_Value)); + _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _STD move(_Value)); } } else { - return expected<_Uty, _Err>(unexpect, _STD move(this->_Unexpected)); + return expected<_Uty, _Err>(unexpect, _STD move(_Unexpected)); } } @@ -939,11 +939,11 @@ public: constexpr auto transform_error(_Fn&& _Func) & { using _Uty = remove_cv_t>; - if (this->_Has_value) { - return expected<_Ty, _Uty>(in_place, this->_Value); + if (_Has_value) { + return expected<_Ty, _Uty>(in_place, _Value); } else { return expected<_Ty, _Uty>( - _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), this->_Unexpected); + _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), _Unexpected); } } @@ -952,11 +952,11 @@ public: constexpr auto transform_error(_Fn&& _Func) const& { using _Uty = remove_cv_t>; - if (this->_Has_value) { - return expected<_Ty, _Uty>(in_place, this->_Value); + if (_Has_value) { + return expected<_Ty, _Uty>(in_place, _Value); } else { return expected<_Ty, _Uty>( - _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), this->_Unexpected); + _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), _Unexpected); } } @@ -965,11 +965,11 @@ public: constexpr auto transform_error(_Fn&& _Func) && { using _Uty = remove_cv_t>; - if (this->_Has_value) { - return expected<_Ty, _Uty>(in_place, _STD move(this->_Value)); + if (_Has_value) { + return expected<_Ty, _Uty>(in_place, _STD move(_Value)); } else { return expected<_Ty, _Uty>(_Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), - _STD move(this->_Unexpected)); + _STD move(_Unexpected)); } } @@ -978,11 +978,11 @@ public: constexpr auto transform_error(_Fn&& _Func) const&& { using _Uty = remove_cv_t>; - if (this->_Has_value) { - return expected<_Ty, _Uty>(in_place, _STD move(this->_Value)); + if (_Has_value) { + return expected<_Ty, _Uty>(in_place, _STD move(_Value)); } else { return expected<_Ty, _Uty>(_Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), - _STD move(this->_Unexpected)); + _STD move(_Unexpected)); } } @@ -1393,10 +1393,10 @@ public: "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.object.monadic]/3."); - if (this->_Has_value) { + if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func)); } else { - return _Uty(unexpect, this->_Unexpected); + return _Uty(unexpect, _Unexpected); } } @@ -1409,10 +1409,10 @@ public: "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.object.monadic]/3."); - if (this->_Has_value) { + if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func)); } else { - return _Uty(unexpect, this->_Unexpected); + return _Uty(unexpect, _Unexpected); } } @@ -1425,10 +1425,10 @@ public: "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.object.monadic]/7."); - if (this->_Has_value) { + if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func)); } else { - return _Uty(unexpect, _STD move(this->_Unexpected)); + return _Uty(unexpect, _STD move(_Unexpected)); } } @@ -1441,10 +1441,10 @@ public: "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.object.monadic]/7."); - if (this->_Has_value) { + if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func)); } else { - return _Uty(unexpect, _STD move(this->_Unexpected)); + return _Uty(unexpect, _STD move(_Unexpected)); } } @@ -1459,10 +1459,10 @@ public: "expected::or_else(F) requires the value type of the return type of F to be T" "N4928 [expected.object.monadic]/11."); - if (this->_Has_value) { + if (_Has_value) { return _Uty(); } else { - return _STD invoke(_STD forward<_Fn>(_Func), this->_Unexpected); + return _STD invoke(_STD forward<_Fn>(_Func), _Unexpected); } } @@ -1477,10 +1477,10 @@ public: "expected::or_else(F) requires the value type of the return type of F to be T" "N4928 [expected.object.monadic]/11."); - if (this->_Has_value) { + if (_Has_value) { return _Uty(); } else { - return _STD invoke(_STD forward<_Fn>(_Func), this->_Unexpected); + return _STD invoke(_STD forward<_Fn>(_Func), _Unexpected); } } @@ -1495,10 +1495,10 @@ public: "expected::or_else(F) requires the value type of the return type of F to be T" "N4928 [expected.object.monadic]/11."); - if (this->_Has_value) { + if (_Has_value) { return _Uty(); } else { - return _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Unexpected)); + return _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Unexpected)); } } @@ -1513,10 +1513,10 @@ public: "expected::or_else(F) requires the value type of the return type of F to be T" "N4928 [expected.object.monadic]/11."); - if (this->_Has_value) { + if (_Has_value) { return _Uty(); } else { - return _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Unexpected)); + return _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Unexpected)); } } @@ -1525,7 +1525,7 @@ public: constexpr auto transform(_Fn&& _Func) & { using _Uty = remove_cv_t>; - if (this->_Has_value) { + if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func)); return expected<_Uty, _Err>(); @@ -1533,7 +1533,7 @@ public: return expected<_Uty, _Err>(_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); } } else { - return expected<_Uty, _Err>(unexpect, this->_Unexpected); + return expected<_Uty, _Err>(unexpect, _Unexpected); } } @@ -1542,7 +1542,7 @@ public: constexpr auto transform(_Fn&& _Func) const& { using _Uty = remove_cv_t>; - if (this->_Has_value) { + if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func)); return expected<_Uty, _Err>(); @@ -1550,7 +1550,7 @@ public: return expected<_Uty, _Err>(_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); } } else { - return expected<_Uty, _Err>(unexpect, this->_Unexpected); + return expected<_Uty, _Err>(unexpect, _Unexpected); } } @@ -1560,7 +1560,7 @@ public: constexpr auto transform(_Fn&& _Func) && { using _Uty = remove_cv_t>; - if (this->_Has_value) { + if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func)); return expected<_Uty, _Err>(); @@ -1568,7 +1568,7 @@ public: return expected<_Uty, _Err>(_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); } } else { - return expected<_Uty, _Err>(unexpect, _STD move(this->_Unexpected)); + return expected<_Uty, _Err>(unexpect, _STD move(_Unexpected)); } } @@ -1577,7 +1577,7 @@ public: constexpr auto transform(_Fn&& _Func) const&& { using _Uty = remove_cv_t>; - if (this->_Has_value) { + if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func)); return expected<_Uty, _Err>(); @@ -1585,7 +1585,7 @@ public: return expected<_Uty, _Err>(_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); } } else { - return expected<_Uty, _Err>(unexpect, _STD move(this->_Unexpected)); + return expected<_Uty, _Err>(unexpect, _STD move(_Unexpected)); } } @@ -1593,11 +1593,11 @@ public: constexpr auto transform_error(_Fn&& _Func) & { using _Uty = remove_cv_t>; - if (this->_Has_value) { + if (_Has_value) { return expected<_Ty, _Uty>(); } else { return expected<_Ty, _Uty>( - _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), this->_Unexpected); + _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), _Unexpected); } } @@ -1605,11 +1605,11 @@ public: constexpr auto transform_error(_Fn&& _Func) const& { using _Uty = remove_cv_t>; - if (this->_Has_value) { + if (_Has_value) { return expected<_Ty, _Uty>(); } else { return expected<_Ty, _Uty>( - _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), this->_Unexpected); + _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), _Unexpected); } } @@ -1617,11 +1617,11 @@ public: constexpr auto transform_error(_Fn&& _Func) && { using _Uty = remove_cv_t>; - if (this->_Has_value) { + if (_Has_value) { return expected<_Ty, _Uty>(); } else { return expected<_Ty, _Uty>(_Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), - _STD move(this->_Unexpected)); + _STD move(_Unexpected)); } } @@ -1629,11 +1629,11 @@ public: constexpr auto transform_error(_Fn&& _Func) const&& { using _Uty = remove_cv_t>; - if (this->_Has_value) { + if (_Has_value) { return expected<_Ty, _Uty>(); } else { return expected<_Ty, _Uty>(_Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), - _STD move(this->_Unexpected)); + _STD move(_Unexpected)); } } diff --git a/tests/std/tests/P0798R8_monadic_operations_for_std_optional/env.lst b/tests/std/tests/P0798R8_monadic_operations_for_std_optional/env.lst index 642f530ffad..8ac7033b206 100644 --- a/tests/std/tests/P0798R8_monadic_operations_for_std_optional/env.lst +++ b/tests/std/tests/P0798R8_monadic_operations_for_std_optional/env.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -RUNALL_INCLUDE ..\usual_latest_matrix.lst +RUNALL_INCLUDE ..\strict_concepts_latest_matrix.lst From e80e0a31550adb994ee6af4e3ea950ee82816d1e Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Thu, 26 Jan 2023 09:20:27 +0000 Subject: [PATCH 10/50] Rename test variables --- .../test.cpp | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp index ca902ce28c1..ab892f60ae7 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -46,45 +46,45 @@ struct Thingy { }; template -constexpr void test_impl(Expected&& exp, Expected&& unexp) { - assert(exp.has_value()); - assert(!unexp.has_value()); +constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { + assert(engaged.has_value()); + assert(!unengaged.has_value()); using Val = typename remove_cvref_t::value_type; auto succeed = [](auto...) { return expected{33}; }; auto fail = [](auto...) { return expected(unexpect, 44); }; { - decltype(auto) result = forward(exp).and_then(succeed); + decltype(auto) result = forward(engaged).and_then(succeed); static_assert(is_same_v>); assert(result == 33); } { - decltype(auto) result = forward(unexp).and_then(succeed); + decltype(auto) result = forward(unengaged).and_then(succeed); static_assert(is_same_v>); assert(!result); assert(result.error() == 22); } { - decltype(auto) result = forward(exp).and_then(fail); + decltype(auto) result = forward(engaged).and_then(fail); static_assert(is_same_v>); assert(!result); assert(result.error() == 44); } { - decltype(auto) result = forward(unexp).and_then(fail); + decltype(auto) result = forward(unengaged).and_then(fail); static_assert(is_same_v>); assert(!result); assert(result.error() == 22); } if constexpr (!is_void_v) { { - decltype(auto) result = forward(exp).and_then(&Thingy::x); + decltype(auto) result = forward(engaged).and_then(&Thingy::x); static_assert(is_same_v>); assert(result == 11); } { - decltype(auto) result = forward(unexp).and_then(&Thingy::x); + decltype(auto) result = forward(unengaged).and_then(&Thingy::x); static_assert(is_same_v>); assert(result.error() == 22); } @@ -95,46 +95,46 @@ constexpr void test_impl(Expected&& exp, Expected&& unexp) { auto to_void = [](auto...) { return; }; { - decltype(auto) result = forward(exp).transform(f); + decltype(auto) result = forward(engaged).transform(f); static_assert(is_same_v>); assert(result == 55); } { - decltype(auto) result = forward(unexp).transform(f); + decltype(auto) result = forward(unengaged).transform(f); static_assert(is_same_v>); assert(!result); assert(result.error() == 22); } if constexpr (!is_void_v) { { - decltype(auto) result = forward(exp).transform(&Thingy::member_func); + decltype(auto) result = forward(engaged).transform(&Thingy::member_func); static_assert(is_same_v>); assert(result == 66); } { - decltype(auto) result = forward(unexp).transform(&Thingy::member_func); + decltype(auto) result = forward(unengaged).transform(&Thingy::member_func); static_assert(is_same_v>); assert(result.error() == 22); } } { - decltype(auto) result = forward(exp).transform(immov); + decltype(auto) result = forward(engaged).transform(immov); static_assert(is_same_v>); assert(result->v == 88); } { - decltype(auto) result = forward(unexp).transform(immov); + decltype(auto) result = forward(unengaged).transform(immov); static_assert(is_same_v>); assert(!result); assert(result.error() == 22); } { - decltype(auto) result = forward(exp).transform(to_void); + decltype(auto) result = forward(engaged).transform(to_void); static_assert(is_same_v>); assert(result); } { - decltype(auto) result = forward(unexp).transform(to_void); + decltype(auto) result = forward(unengaged).transform(to_void); static_assert(is_same_v>); assert(!result); assert(result.error() == 22); @@ -144,7 +144,7 @@ constexpr void test_impl(Expected&& exp, Expected&& unexp) { auto to_thingy = [](int i) { return Thingy{i}; }; { - decltype(auto) result = forward(exp).transform_error(to_thingy); + decltype(auto) result = forward(engaged).transform_error(to_thingy); static_assert(is_same_v>); assert(result); if constexpr (!is_void_v) { @@ -152,13 +152,13 @@ constexpr void test_impl(Expected&& exp, Expected&& unexp) { } } { - decltype(auto) result = forward(unexp).transform_error(to_thingy); + decltype(auto) result = forward(unengaged).transform_error(to_thingy); static_assert(is_same_v>); assert(!result); assert(result.error().x == 22); } { - decltype(auto) result = forward(exp).transform_error(to_thingy).transform_error(&Thingy::member_func); + decltype(auto) result = forward(engaged).transform_error(to_thingy).transform_error(&Thingy::member_func); static_assert(is_same_v>); if constexpr (!is_void_v) { assert(result->x == 11); @@ -166,20 +166,20 @@ constexpr void test_impl(Expected&& exp, Expected&& unexp) { } { decltype(auto) result = - forward(unexp).transform_error(to_thingy).transform_error(&Thingy::member_func); + forward(unengaged).transform_error(to_thingy).transform_error(&Thingy::member_func); static_assert(is_same_v>); assert(!result); assert(result.error() == 66); } { - decltype(auto) result = forward(exp).transform_error(immov); + decltype(auto) result = forward(engaged).transform_error(immov); static_assert(is_same_v>); if constexpr (!is_void_v) { assert(result->x == 11); } } { - decltype(auto) result = forward(unexp).transform_error(immov); + decltype(auto) result = forward(unengaged).transform_error(immov); static_assert(is_same_v>); assert(!result); assert(result.error().v == 88); @@ -193,7 +193,7 @@ constexpr void test_impl(Expected&& exp, Expected&& unexp) { } }; { - decltype(auto) result = forward(exp).or_else(to_expected_thingy); + decltype(auto) result = forward(engaged).or_else(to_expected_thingy); static_assert(is_same_v>); assert(result); if constexpr (!is_void_v) { @@ -201,7 +201,7 @@ constexpr void test_impl(Expected&& exp, Expected&& unexp) { } } { - decltype(auto) result = forward(unexp).or_else(to_expected_thingy); + decltype(auto) result = forward(unengaged).or_else(to_expected_thingy); static_assert(is_same_v>); assert(result); if constexpr (!is_void_v) { @@ -300,21 +300,21 @@ constexpr void test_error_or() noexcept { constexpr void test_monadic() { { - expected exp{Thingy{11}}; - expected unexp{std::unexpect, 22}; - test_impl(exp, unexp); - test_impl(as_const(exp), as_const(unexp)); - test_impl(move(exp), move(unexp)); - test_impl(move(as_const(exp)), move(as_const(unexp))); + expected engaged{Thingy{11}}; + expected unengaged{std::unexpect, 22}; + test_impl(engaged, unengaged); + test_impl(as_const(engaged), as_const(unengaged)); + test_impl(move(engaged), move(unengaged)); + test_impl(move(as_const(engaged)), move(as_const(unengaged))); } { - expected exp{}; - expected unexp{std::unexpect, 22}; - test_impl(exp, unexp); - test_impl(as_const(exp), as_const(unexp)); - test_impl(move(exp), move(unexp)); - test_impl(move(as_const(exp)), move(as_const(unexp))); + expected engaged{}; + expected unengaged{std::unexpect, 22}; + test_impl(engaged, unengaged); + test_impl(as_const(engaged), as_const(unengaged)); + test_impl(move(engaged), move(unengaged)); + test_impl(move(as_const(engaged)), move(as_const(unengaged))); } } From 54f2c16451edd209bf4e6f0fe1750985769c5c7b Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Thu, 26 Jan 2023 09:22:29 +0000 Subject: [PATCH 11/50] Add const to tests --- .../test.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp index ab892f60ae7..8a6118c5851 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -28,7 +28,7 @@ struct convertible { }; struct Immovable { - constexpr Immovable(int x) : v(x) {} + constexpr Immovable(const int x) : v(x) {} Immovable(const Immovable&) = delete; Immovable(Immovable&&) = delete; Immovable& operator=(const Immovable&) = delete; @@ -51,8 +51,8 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { assert(!unengaged.has_value()); using Val = typename remove_cvref_t::value_type; - auto succeed = [](auto...) { return expected{33}; }; - auto fail = [](auto...) { return expected(unexpect, 44); }; + const auto succeed = [](auto...) { return expected{33}; }; + const auto fail = [](auto...) { return expected(unexpect, 44); }; { decltype(auto) result = forward(engaged).and_then(succeed); @@ -90,9 +90,9 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { } } - auto f = [](auto...) { return 55; }; - auto immov = [](auto...) { return Immovable{88}; }; - auto to_void = [](auto...) { return; }; + const auto f = [](auto...) { return 55; }; + const auto immov = [](auto...) { return Immovable{88}; }; + const auto to_void = [](auto...) { return; }; { decltype(auto) result = forward(engaged).transform(f); @@ -141,7 +141,7 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { } - auto to_thingy = [](int i) { return Thingy{i}; }; + const auto to_thingy = [](int i) { return Thingy{i}; }; { decltype(auto) result = forward(engaged).transform_error(to_thingy); @@ -185,7 +185,7 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { assert(result.error().v == 88); } - auto to_expected_thingy = [](auto...) { + const auto to_expected_thingy = [](auto...) { if constexpr (is_void_v) { return expected{}; } else { From f8ec9afcb05bb27b5bc53d1c3c6af48774b99771 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Thu, 26 Jan 2023 09:31:42 +0000 Subject: [PATCH 12/50] Update test expectations for libc++ --- tests/libcxx/expected_results.txt | 3 +++ tests/libcxx/skipped_tests.txt | 2 ++ 2 files changed, 5 insertions(+) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 764505bbc2c..25b1cf3f74f 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -231,6 +231,9 @@ std/utilities/format/format.tuple/set_separator.pass.cpp FAIL std/depr/depr.c.headers/uchar_h.compile.pass.cpp FAIL std/strings/c.strings/cuchar.compile.pass.cpp FAIL +# P2505R5 "Monadic Functions for std::expected" +std/language.support/support.limits/support.limits.general/expected.version.compile.pass.cpp FAIL + # *** MISSING COMPILER FEATURES *** # Nothing here! :-) diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 428e61c57c8..59bb191e242 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -231,6 +231,8 @@ utilities\format\format.tuple\set_separator.pass.cpp depr\depr.c.headers\uchar_h.compile.pass.cpp strings\c.strings\cuchar.compile.pass.cpp +# P2505R5 "Monadic Functions for std::expected" +std/language.support/support.limits/support.limits.general/expected.version.compile.pass.cpp FAIL # *** MISSING COMPILER FEATURES *** # Nothing here! :-) From 6ec9f92eb812b7cf7b6b888639c74056d91bc3ec Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Thu, 26 Jan 2023 09:43:57 +0000 Subject: [PATCH 13/50] Revert optional test change --- .../tests/P0798R8_monadic_operations_for_std_optional/env.lst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P0798R8_monadic_operations_for_std_optional/env.lst b/tests/std/tests/P0798R8_monadic_operations_for_std_optional/env.lst index 8ac7033b206..642f530ffad 100644 --- a/tests/std/tests/P0798R8_monadic_operations_for_std_optional/env.lst +++ b/tests/std/tests/P0798R8_monadic_operations_for_std_optional/env.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -RUNALL_INCLUDE ..\strict_concepts_latest_matrix.lst +RUNALL_INCLUDE ..\usual_latest_matrix.lst From fad097289b71c559adf38199eb563c184db76215 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Thu, 26 Jan 2023 10:35:26 +0000 Subject: [PATCH 14/50] Remove std qualification --- .../P2505R5_monadic_functions_for_std_expected/test.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp index 8a6118c5851..d095ba73ced 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -208,6 +208,8 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { assert(result.value().x == 77); } } + + engaged.transform([](auto...) { return ""; }); } template @@ -301,7 +303,7 @@ constexpr void test_error_or() noexcept { constexpr void test_monadic() { { expected engaged{Thingy{11}}; - expected unengaged{std::unexpect, 22}; + expected unengaged{unexpect, 22}; test_impl(engaged, unengaged); test_impl(as_const(engaged), as_const(unengaged)); test_impl(move(engaged), move(unengaged)); @@ -310,7 +312,7 @@ constexpr void test_monadic() { { expected engaged{}; - expected unengaged{std::unexpect, 22}; + expected unengaged{unexpect, 22}; test_impl(engaged, unengaged); test_impl(as_const(engaged), as_const(unengaged)); test_impl(move(engaged), move(unengaged)); From c9118c274715032ff6040016582aa3bddad74788 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Thu, 26 Jan 2023 11:22:14 +0000 Subject: [PATCH 15/50] Clang format --- .../tests/P2505R5_monadic_functions_for_std_expected/test.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp index d095ba73ced..059d4883448 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -158,7 +158,8 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { assert(result.error().x == 22); } { - decltype(auto) result = forward(engaged).transform_error(to_thingy).transform_error(&Thingy::member_func); + decltype(auto) result = + forward(engaged).transform_error(to_thingy).transform_error(&Thingy::member_func); static_assert(is_same_v>); if constexpr (!is_void_v) { assert(result->x == 11); From 81524354151d192abee7de22303c6b33edbf3743 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Mon, 30 Jan 2023 09:42:16 +0000 Subject: [PATCH 16/50] Update expected and skipped results --- tests/libcxx/expected_results.txt | 6 ++---- tests/libcxx/skipped_tests.txt | 5 ++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 25b1cf3f74f..f17c93e9713 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -72,6 +72,8 @@ std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_deallocate_ma # Too many constexpr operations std/utilities/charconv/charconv.to.chars/integral.pass.cpp FAIL +# libc++ has not implemented P2505R5: "Monadic Functions for std::expected" +std/language.support/support.limits/support.limits.general/expected.version.compile.pass.cpp FAIL # *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX *** # Tracked by VSO-593630 " Enable libcxx filesystem tests" @@ -231,10 +233,6 @@ std/utilities/format/format.tuple/set_separator.pass.cpp FAIL std/depr/depr.c.headers/uchar_h.compile.pass.cpp FAIL std/strings/c.strings/cuchar.compile.pass.cpp FAIL -# P2505R5 "Monadic Functions for std::expected" -std/language.support/support.limits/support.limits.general/expected.version.compile.pass.cpp FAIL - - # *** MISSING COMPILER FEATURES *** # Nothing here! :-) diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 59bb191e242..513e018ff61 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -72,6 +72,8 @@ utilities\utility\mem.res\mem.res.pool\mem.res.pool.mem\unsync_deallocate_matche # Too many constexpr operations utilities\charconv\charconv.to.chars\integral.pass.cpp +# libc++ has not implemented P2505R5: "Monadic Functions for std::expected" +std/language.support/support.limits/support.limits.general/expected.version.compile.pass.cpp # *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX *** # Tracked by VSO-593630 " Enable libcxx filesystem tests" @@ -231,9 +233,6 @@ utilities\format\format.tuple\set_separator.pass.cpp depr\depr.c.headers\uchar_h.compile.pass.cpp strings\c.strings\cuchar.compile.pass.cpp -# P2505R5 "Monadic Functions for std::expected" -std/language.support/support.limits/support.limits.general/expected.version.compile.pass.cpp FAIL - # *** MISSING COMPILER FEATURES *** # Nothing here! :-) From 8a2591115776e0d294c3ef232619740293bfed0a Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Mon, 30 Jan 2023 09:43:51 +0000 Subject: [PATCH 17/50] Remove extra newlines --- stl/inc/expected | 2 -- .../tests/P2505R5_monadic_functions_for_std_expected/test.cpp | 2 -- 2 files changed, 4 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index 742134afd8f..3c1ee1ff4f1 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -897,7 +897,6 @@ public: } } - template requires is_move_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) && { @@ -1554,7 +1553,6 @@ public: } } - template requires is_move_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) && { diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp index 059d4883448..fb63b86aeab 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -140,7 +140,6 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { assert(result.error() == 22); } - const auto to_thingy = [](int i) { return Thingy{i}; }; { @@ -321,7 +320,6 @@ constexpr void test_monadic() { } } - constexpr bool test() { test_error_or(); test_monadic(); From d79e935362aa59f87c4cfaa85849ffa3781f3afb Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Mon, 30 Jan 2023 09:46:53 +0000 Subject: [PATCH 18/50] Change test matrix Co-authored-by: Casey Carter --- .../tests/P2505R5_monadic_functions_for_std_expected/env.lst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/env.lst b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/env.lst index 8ac7033b206..18e2d7c71ec 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/env.lst +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/env.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -RUNALL_INCLUDE ..\strict_concepts_latest_matrix.lst +RUNALL_INCLUDE ..\concepts_latest_matrix.lst From d1af894f4c5f825f162d406c1bc99ab630cfc0ee Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Mon, 30 Jan 2023 09:47:36 +0000 Subject: [PATCH 19/50] Change typename to class Co-authored-by: Casey Carter --- .../tests/P2505R5_monadic_functions_for_std_expected/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp index fb63b86aeab..14089f2457a 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -11,7 +11,7 @@ using namespace std; enum class IsNothrowConstructible : bool { Not, Yes }; enum class IsNothrowConvertible : bool { Not, Yes }; -template +template [[nodiscard]] constexpr bool IsYes(const E e) noexcept { return e == E::Yes; } From 5d208a6e142a1803271c35eed45712b295b397e1 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Mon, 30 Jan 2023 09:48:24 +0000 Subject: [PATCH 20/50] Change static assert message to reflect standard Co-authored-by: Casey Carter --- stl/inc/expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/expected b/stl/inc/expected index 3c1ee1ff4f1..bea3bdafeed 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -695,7 +695,7 @@ public: static_assert( is_copy_constructible_v<_Err>, "is_copy_constructible_v must be true. (N4928 [expected.object.obs]/20)"); static_assert( - is_convertible_v<_Uty, _Err>, "is_convertible_v must be true. (N4928 [expected.object.obs]/20)"); + is_convertible_v<_Uty, _Err>, "is_convertible_v must be true. (N4928 [expected.object.obs]/20)"); if (_Has_value) { return _STD forward<_Uty>(_Other); From 0a5d86670d560fdd7d23d88619389d313e79878e Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Mon, 30 Jan 2023 09:48:57 +0000 Subject: [PATCH 21/50] Change static assert message to reflect standard Co-authored-by: Casey Carter --- stl/inc/expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/expected b/stl/inc/expected index bea3bdafeed..7bb8cbdfd03 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -710,7 +710,7 @@ public: static_assert( is_move_constructible_v<_Err>, "is_move_constructible_v must be true. (N4928 [expected.object.obs]/22)"); static_assert( - is_convertible_v<_Uty, _Err>, "is_convertible_v must be true. (N4928 [expected.object.obs]/22)"); + is_convertible_v<_Uty, _Err>, "is_convertible_v must be true. (N4928 [expected.object.obs]/22)"); if (_Has_value) { return _STD forward<_Uty>(_Other); From ad69aa54946f51bb315fa2ce5698604e177917d4 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Mon, 30 Jan 2023 09:49:37 +0000 Subject: [PATCH 22/50] Remove bad ref qualifier from function type Co-authored-by: Casey Carter --- stl/inc/expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/expected b/stl/inc/expected index 7bb8cbdfd03..30f9ac760c6 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -1556,7 +1556,7 @@ public: template requires is_move_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) && { - using _Uty = remove_cv_t>; + using _Uty = remove_cv_t>; if (_Has_value) { if constexpr (is_void_v<_Uty>) { From fbf5e815a001b7e201ce5720f4182f21d27d70c3 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Mon, 30 Jan 2023 09:54:16 +0000 Subject: [PATCH 23/50] Fix standards citations --- stl/inc/expected | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index 3c1ee1ff4f1..2608c832b50 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -1381,7 +1381,7 @@ public: } } - // [expected.object.monadic] + // [expected.void.monadic] template requires is_copy_constructible_v<_Err> @@ -1390,7 +1390,7 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/3."); + "N4928 [expected.void.monadic]/3."); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func)); @@ -1406,7 +1406,7 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/3."); + "N4928 [expected.void.monadic]/3."); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func)); @@ -1422,7 +1422,7 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/7."); + "N4928 [expected.void.monadic]/7."); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func)); @@ -1438,7 +1438,7 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/7."); + "N4928 [expected.void.monadic]/7."); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func)); @@ -1453,10 +1453,10 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::or_else(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/11."); + "N4928 [expected.void.monadic]/10."); static_assert(is_same_v, "expected::or_else(F) requires the value type of the return type of F to be T" - "N4928 [expected.object.monadic]/11."); + "N4928 [expected.void.monadic]/10."); if (_Has_value) { return _Uty(); @@ -1471,10 +1471,10 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::or_else(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/11."); + "N4928 [expected.void.monadic]/10."); static_assert(is_same_v, "expected::or_else(F) requires the value type of the return type of F to be T" - "N4928 [expected.object.monadic]/11."); + "N4928 [expected.void.monadic]/10."); if (_Has_value) { return _Uty(); @@ -1489,10 +1489,10 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::or_else(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/11."); + "N4928 [expected.void.monadic]/13."); static_assert(is_same_v, "expected::or_else(F) requires the value type of the return type of F to be T" - "N4928 [expected.object.monadic]/11."); + "N4928 [expected.void.monadic]/13."); if (_Has_value) { return _Uty(); @@ -1507,10 +1507,10 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::or_else(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/11."); + "N4928 [expected.void.monadic]/13."); static_assert(is_same_v, "expected::or_else(F) requires the value type of the return type of F to be T" - "N4928 [expected.object.monadic]/11."); + "N4928 [expected.void.monadic]/13."); if (_Has_value) { return _Uty(); From 46c2340294df248db0c7ce7918061057d7ff0bbb Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Mon, 30 Jan 2023 09:56:17 +0000 Subject: [PATCH 24/50] Fix more citations --- stl/inc/expected | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index decdf817774..023be88336c 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -1355,9 +1355,9 @@ public: _NODISCARD constexpr _Err error_or(_Uty&& _Other) const& noexcept( is_nothrow_copy_constructible_v<_Err>&& is_nothrow_convertible_v<_Uty, _Err>) { // strengthened static_assert( - is_copy_constructible_v<_Err>, "is_copy_constructible_v must be true. (N4928 [expected.object.obs]/20)"); + is_copy_constructible_v<_Err>, "is_copy_constructible_v must be true. (N4928 [expected.void.obs]/9)"); static_assert( - is_convertible_v<_Uty, _Err>, "is_convertible_v must be true. (N4928 [expected.object.obs]/20)"); + is_convertible_v<_Uty, _Err>, "is_convertible_v must be true. (N4928 [expected.void.obs]/9)"); if (_Has_value) { return _STD forward<_Uty>(_Other); @@ -1370,9 +1370,9 @@ public: _NODISCARD constexpr _Err error_or(_Uty&& _Other) && noexcept( is_nothrow_move_constructible_v<_Err>&& is_nothrow_convertible_v<_Uty, _Err>) { // strengthened static_assert( - is_move_constructible_v<_Err>, "is_move_constructible_v must be true. (N4928 [expected.object.obs]/22)"); + is_move_constructible_v<_Err>, "is_move_constructible_v must be true. (N4928 [expected.void.obs]/11)"); static_assert( - is_convertible_v<_Uty, _Err>, "is_convertible_v must be true. (N4928 [expected.object.obs]/22)"); + is_convertible_v<_Uty, _Err>, "is_convertible_v must be true. (N4928 [expected.void.obs]/11)"); if (_Has_value) { return _STD forward<_Uty>(_Other); From fadf2f47da19b9d858860fdd79b600e1628b1ca0 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Mon, 30 Jan 2023 10:04:26 +0000 Subject: [PATCH 25/50] Fix more standards citations --- stl/inc/expected | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index 023be88336c..f1c16b38869 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -830,10 +830,10 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::or_else(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/11."); + "N4928 [expected.object.monadic]/13."); static_assert(is_same_v, "expected::or_else(F) requires the value type of the return type of F to be T" - "N4928 [expected.object.monadic]/11."); + "N4928 [expected.object.monadic]/13."); if (_Has_value) { return _Uty(in_place, _STD move(_Value)); @@ -849,10 +849,10 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::or_else(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/11."); + "N4928 [expected.object.monadic]/13."); static_assert(is_same_v, "expected::or_else(F) requires the value type of the return type of F to be T" - "N4928 [expected.object.monadic]/11."); + "N4928 [expected.object.monadic]/13."); if (_Has_value) { return _Uty(in_place, _STD move(_Value)); From 1cedf672f6c5153c0649a2ca62efd0b66aa94811 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Mon, 30 Jan 2023 10:05:14 +0000 Subject: [PATCH 26/50] Fix more standards citations --- stl/inc/expected | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index f1c16b38869..8ece825782f 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -830,10 +830,10 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::or_else(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/13."); + "N4928 [expected.object.monadic]/15."); static_assert(is_same_v, "expected::or_else(F) requires the value type of the return type of F to be T" - "N4928 [expected.object.monadic]/13."); + "N4928 [expected.object.monadic]/15."); if (_Has_value) { return _Uty(in_place, _STD move(_Value)); @@ -849,10 +849,10 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::or_else(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/13."); + "N4928 [expected.object.monadic]/15."); static_assert(is_same_v, "expected::or_else(F) requires the value type of the return type of F to be T" - "N4928 [expected.object.monadic]/13."); + "N4928 [expected.object.monadic]/15."); if (_Has_value) { return _Uty(in_place, _STD move(_Value)); From c76f98fae36a687ff66286723fe1c5db24b011df Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Mon, 30 Jan 2023 10:07:01 +0000 Subject: [PATCH 27/50] Remove && from type trait arguments which will go through declval --- stl/inc/expected | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index 8ece825782f..179908274e7 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -756,7 +756,7 @@ public: template requires is_move_constructible_v<_Err> constexpr auto and_then(_Fn&& _Func) && { - using _Uty = remove_cvref_t>; + using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected " @@ -772,7 +772,7 @@ public: template requires is_move_constructible_v<_Err> constexpr auto and_then(_Fn&& _Func) const&& { - using _Uty = remove_cvref_t>; + using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected " @@ -826,7 +826,7 @@ public: template requires is_move_constructible_v<_Ty> constexpr auto or_else(_Fn&& _Func) && { - using _Uty = remove_cvref_t>; + using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, "expected::or_else(F) requires the return type of F to be a specialization of expected " @@ -845,7 +845,7 @@ public: template requires is_move_constructible_v<_Ty> constexpr auto or_else(_Fn&& _Func) const&& { - using _Uty = remove_cvref_t>; + using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, "expected::or_else(F) requires the return type of F to be a specialization of expected " @@ -900,7 +900,7 @@ public: template requires is_move_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) && { - using _Uty = remove_cv_t>; + using _Uty = remove_cv_t>; if (_Has_value) { if constexpr (is_void_v<_Uty>) { @@ -918,7 +918,7 @@ public: template requires is_move_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) const&& { - using _Uty = remove_cv_t>; + using _Uty = remove_cv_t>; if (_Has_value) { if constexpr (is_void_v<_Uty>) { @@ -962,7 +962,7 @@ public: template requires is_move_constructible_v<_Ty> constexpr auto transform_error(_Fn&& _Func) && { - using _Uty = remove_cv_t>; + using _Uty = remove_cv_t>; if (_Has_value) { return expected<_Ty, _Uty>(in_place, _STD move(_Value)); @@ -975,7 +975,7 @@ public: template requires is_move_constructible_v<_Ty> constexpr auto transform_error(_Fn&& _Func) const&& { - using _Uty = remove_cv_t>; + using _Uty = remove_cv_t>; if (_Has_value) { return expected<_Ty, _Uty>(in_place, _STD move(_Value)); From ac441f4d26453dc426214f2bfb2459b217d32a5c Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Mon, 30 Jan 2023 10:48:45 +0000 Subject: [PATCH 28/50] Add static_asserts for and_then --- stl/inc/expected | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/stl/inc/expected b/stl/inc/expected index 179908274e7..9707490aa1b 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -729,6 +729,9 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.object.monadic]/3."); + static_assert(is_same_v), + "expected::and_then(F) requires the error type of the return type of F to be E " + "N4928 [expected.object.monadic]/3."); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func), _Value); @@ -745,6 +748,9 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.object.monadic]/3."); + static_assert(is_same_v), + "expected::and_then(F) requires the error type of the return type of F to be E " + "N4928 [expected.object.monadic]/3."); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func), _Value); @@ -761,6 +767,9 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.object.monadic]/7."); + static_assert(is_same_v), + "expected::and_then(F) requires the error type of the return type of F to be E " + "N4928 [expected.object.monadic]/7."); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Value)); @@ -777,6 +786,9 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.object.monadic]/7."); + static_assert(is_same_v), + "expected::and_then(F) requires the error type of the return type of F to be E " + "N4928 [expected.object.monadic]/7."); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Value)); From ab446edcc49320d45f32a48587ff649b751a026e Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Mon, 30 Jan 2023 12:59:45 +0000 Subject: [PATCH 29/50] Correct slashes --- stl/inc/expected | 64 +++++++++++++++++----------------- tests/libcxx/skipped_tests.txt | 2 +- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index 9707490aa1b..fe24482cc02 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -727,11 +727,11 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/3."); + "expected::and_then(F) requires the return type of F to be a specialization of expected. " + "(N4928 [expected.object.monadic]/3)."); static_assert(is_same_v), - "expected::and_then(F) requires the error type of the return type of F to be E " - "N4928 [expected.object.monadic]/3."); + "expected::and_then(F) requires the error type of the return type of F to be E. " + "(N4928 [expected.object.monadic]/3)"); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func), _Value); @@ -746,11 +746,11 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/3."); + "expected::and_then(F) requires the return type of F to be a specialization of expected. " + "(N4928 [expected.object.monadic]/3)."); static_assert(is_same_v), - "expected::and_then(F) requires the error type of the return type of F to be E " - "N4928 [expected.object.monadic]/3."); + "expected::and_then(F) requires the error type of the return type of F to be E. " + "(N4928 [expected.object.monadic]/3)"); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func), _Value); @@ -765,11 +765,11 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/7."); + "expected::and_then(F) requires the return type of F to be a specialization of expected. " + "(N4928 [expected.object.monadic]/7)."); static_assert(is_same_v), - "expected::and_then(F) requires the error type of the return type of F to be E " - "N4928 [expected.object.monadic]/7."); + "expected::and_then(F) requires the error type of the return type of F to be E. " + "(N4928 [expected.object.monadic]/7)"); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Value)); @@ -784,11 +784,11 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/7."); + "expected::and_then(F) requires the return type of F to be a specialization of expected. " + "(N4928 [expected.object.monadic]/7)."); static_assert(is_same_v), - "expected::and_then(F) requires the error type of the return type of F to be E " - "N4928 [expected.object.monadic]/7."); + "expected::and_then(F) requires the error type of the return type of F to be E. " + "(N4928 [expected.object.monadic]/7)"); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Value)); @@ -803,11 +803,11 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::or_else(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/11."); + "expected::or_else(F) requires the return type of F to be a specialization of expected. " + "(N4928 [expected.object.monadic]/11)"); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T" - "N4928 [expected.object.monadic]/11."); + "expected::or_else(F) requires the value type of the return type of F to be T. " + "(N4928 [expected.object.monadic]/11)"); if (_Has_value) { return _Uty(in_place, _Value); @@ -822,11 +822,11 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::or_else(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/11."); + "expected::or_else(F) requires the return type of F to be a specialization of expected. " + "(N4928 [expected.object.monadic]/11)"); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T" - "N4928 [expected.object.monadic]/11."); + "expected::or_else(F) requires the value type of the return type of F to be T. " + "(N4928 [expected.object.monadic]/11)"); if (_Has_value) { return _Uty(in_place, _Value); @@ -841,11 +841,11 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::or_else(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/15."); + "expected::or_else(F) requires the return type of F to be a specialization of expected. " + "(N4928 [expected.object.monadic]/15)"); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T" - "N4928 [expected.object.monadic]/15."); + "expected::or_else(F) requires the value type of the return type of F to be T. " + "(N4928 [expected.object.monadic]/15)"); if (_Has_value) { return _Uty(in_place, _STD move(_Value)); @@ -860,11 +860,11 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::or_else(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.object.monadic]/15."); + "expected::or_else(F) requires the return type of F to be a specialization of expected. " + "(N4928 [expected.object.monadic]/15)"); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T" - "N4928 [expected.object.monadic]/15."); + "expected::or_else(F) requires the value type of the return type of F to be T. " + "(N4928 [expected.object.monadic]/15)"); if (_Has_value) { return _Uty(in_place, _STD move(_Value)); diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 513e018ff61..301c3e62e14 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -73,7 +73,7 @@ utilities\utility\mem.res\mem.res.pool\mem.res.pool.mem\unsync_deallocate_matche utilities\charconv\charconv.to.chars\integral.pass.cpp # libc++ has not implemented P2505R5: "Monadic Functions for std::expected" -std/language.support/support.limits/support.limits.general/expected.version.compile.pass.cpp +std\language.support\support.limits\support.limits.general\expected.version.compile.pass.cpp # *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX *** # Tracked by VSO-593630 " Enable libcxx filesystem tests" From 51e227955d63150917e7f6e78b34e5a00ebbf54f Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Tue, 31 Jan 2023 09:45:13 +0000 Subject: [PATCH 30/50] Fix syntax error --- stl/inc/expected | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index fe24482cc02..f0188e27a76 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -729,7 +729,7 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected. " "(N4928 [expected.object.monadic]/3)."); - static_assert(is_same_v), + static_assert(is_same_v, "expected::and_then(F) requires the error type of the return type of F to be E. " "(N4928 [expected.object.monadic]/3)"); @@ -748,7 +748,7 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected. " "(N4928 [expected.object.monadic]/3)."); - static_assert(is_same_v), + static_assert(is_same_v, "expected::and_then(F) requires the error type of the return type of F to be E. " "(N4928 [expected.object.monadic]/3)"); @@ -767,7 +767,7 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected. " "(N4928 [expected.object.monadic]/7)."); - static_assert(is_same_v), + static_assert(is_same_v, "expected::and_then(F) requires the error type of the return type of F to be E. " "(N4928 [expected.object.monadic]/7)"); @@ -786,7 +786,7 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected. " "(N4928 [expected.object.monadic]/7)."); - static_assert(is_same_v), + static_assert(is_same_v, "expected::and_then(F) requires the error type of the return type of F to be E. " "(N4928 [expected.object.monadic]/7)"); From 2bf4e1ca5db942315e46076f6834b7f1802c65ba Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Tue, 31 Jan 2023 09:46:32 +0000 Subject: [PATCH 31/50] Remove unnecessary default constructor in test --- .../tests/P2505R5_monadic_functions_for_std_expected/test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp index 14089f2457a..975f967ea51 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -17,7 +17,6 @@ template } struct convertible { - constexpr convertible() = default; constexpr convertible(const int val) noexcept : _val(val) {} [[nodiscard]] constexpr bool operator==(const int other) const noexcept { From d1fe6927f44b373f2d933f32f08433fbbcae2b46 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Tue, 31 Jan 2023 09:47:07 +0000 Subject: [PATCH 32/50] Use =default instead of {} in test --- .../tests/P2505R5_monadic_functions_for_std_expected/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp index 975f967ea51..7f875f6c251 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -32,7 +32,7 @@ struct Immovable { Immovable(Immovable&&) = delete; Immovable& operator=(const Immovable&) = delete; Immovable& operator=(Immovable&&) = delete; - constexpr ~Immovable() {} + constexpr ~Immovable() = default; int v; }; From 292847dd98bb14d6b879fc9397289f9aac0a78c9 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Tue, 31 Jan 2023 10:02:55 +0000 Subject: [PATCH 33/50] Assert that error_type is int in tests --- .../tests/P2505R5_monadic_functions_for_std_expected/test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp index 7f875f6c251..4579ba6188e 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -48,6 +48,7 @@ template constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { assert(engaged.has_value()); assert(!unengaged.has_value()); + static_assert(is_same_v::error_type, int>); using Val = typename remove_cvref_t::value_type; const auto succeed = [](auto...) { return expected{33}; }; From a2acbdb67c98ea20c8f155f51b87196e704a0424 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Wed, 1 Feb 2023 09:41:45 +0000 Subject: [PATCH 34/50] Fix incorrect comment locations --- stl/inc/expected | 50 ++++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index f0188e27a76..cfd2125afb2 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -96,7 +96,7 @@ public: // [expected.un.eq] template _NODISCARD_FRIEND constexpr bool operator==(const unexpected& _Left, const unexpected<_UErr>& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Unexpected == _Right.error()))) { // strengthened + noexcept(_Fake_copy_init(_Left._Unexpected == _Right.error()))) /* strengthened */ { return _Left._Unexpected == _Right.error(); } @@ -421,7 +421,7 @@ public: && (is_nothrow_constructible_v<_Ty, _Uty> || is_nothrow_move_constructible_v<_Ty> || is_nothrow_move_constructible_v<_Err>) ) constexpr expected& operator=(_Uty&& _Other) noexcept( - is_nothrow_constructible_v<_Ty, _Uty>&& is_nothrow_assignable_v<_Ty&, _Uty>) { // strengthened + is_nothrow_constructible_v<_Ty, _Uty>&& is_nothrow_assignable_v<_Ty&, _Uty>) /* strengthened */ { if (_Has_value) { _Value = _STD forward<_Uty>(_Other); } else { @@ -437,7 +437,7 @@ public: && (is_nothrow_constructible_v<_Err, const _UErr&> || is_nothrow_move_constructible_v<_Ty> || is_nothrow_move_constructible_v<_Err>) ) constexpr expected& operator=(const unexpected<_UErr>& _Other) noexcept( - is_nothrow_constructible_v<_Err, const _UErr&>&& is_nothrow_assignable_v<_Err&, const _UErr&>) { // strengthened + is_nothrow_constructible_v<_Err, const _UErr&>&& is_nothrow_assignable_v<_Err&, const _UErr&>) /* strengthened */ { if (_Has_value) { _Reinit_expected(_Unexpected, _Value, _Other._Unexpected); _Has_value = false; @@ -453,7 +453,7 @@ public: && (is_nothrow_constructible_v<_Err, _UErr> || is_nothrow_move_constructible_v<_Ty> || is_nothrow_move_constructible_v<_Err>) ) constexpr expected& operator=(unexpected<_UErr>&& _Other) noexcept( - is_nothrow_constructible_v<_Err, _UErr>&& is_nothrow_assignable_v<_Err&, _UErr>) { // strengthened + is_nothrow_constructible_v<_Err, _UErr>&& is_nothrow_assignable_v<_Err&, _UErr>) /* strengthened */ { if (_Has_value) { _Reinit_expected(_Unexpected, _Value, _STD move(_Other._Unexpected)); _Has_value = false; @@ -662,7 +662,7 @@ public: template _NODISCARD constexpr _Ty value_or(_Uty&& _Other) const& noexcept( - is_nothrow_copy_constructible_v<_Ty>&& is_nothrow_convertible_v<_Uty, _Ty>) { // strengthened + is_nothrow_copy_constructible_v<_Ty>&& is_nothrow_convertible_v<_Uty, _Ty>) /* strengthened */ { static_assert( is_copy_constructible_v<_Ty>, "is_copy_constructible_v must be true. (N4910 [expected.object.obs]/16)"); static_assert( @@ -676,7 +676,7 @@ public: } template _NODISCARD constexpr _Ty value_or(_Uty&& _Other) && noexcept( - is_nothrow_move_constructible_v<_Ty>&& is_nothrow_convertible_v<_Uty, _Ty>) { // strengthened + is_nothrow_move_constructible_v<_Ty>&& is_nothrow_convertible_v<_Uty, _Ty>) /* strengthened */ { static_assert( is_move_constructible_v<_Ty>, "is_move_constructible_v must be true. (N4910 [expected.object.obs]/18)"); static_assert( @@ -691,7 +691,7 @@ public: template _NODISCARD constexpr _Err error_or(_Uty&& _Other) const& noexcept( - is_nothrow_copy_constructible_v<_Err>&& is_nothrow_convertible_v<_Uty, _Err>) { // strengthened + is_nothrow_copy_constructible_v<_Err>&& is_nothrow_convertible_v<_Uty, _Err>) /* strengthened */ { static_assert( is_copy_constructible_v<_Err>, "is_copy_constructible_v must be true. (N4928 [expected.object.obs]/20)"); static_assert( @@ -706,7 +706,7 @@ public: template _NODISCARD constexpr _Err error_or(_Uty&& _Other) && noexcept( - is_nothrow_move_constructible_v<_Err>&& is_nothrow_convertible_v<_Uty, _Err>) { // strengthened + is_nothrow_move_constructible_v<_Err>&& is_nothrow_convertible_v<_Uty, _Err>) /* strengthened */ { static_assert( is_move_constructible_v<_Err>, "is_move_constructible_v must be true. (N4928 [expected.object.obs]/22)"); static_assert( @@ -950,6 +950,8 @@ public: constexpr auto transform_error(_Fn&& _Func) & { using _Uty = remove_cv_t>; + static_assert(_Check_unexpected_argument<_Uty>::value); + if (_Has_value) { return expected<_Ty, _Uty>(in_place, _Value); } else { @@ -963,6 +965,8 @@ public: constexpr auto transform_error(_Fn&& _Func) const& { using _Uty = remove_cv_t>; + static_assert(_Check_unexpected_argument<_Uty>::value); + if (_Has_value) { return expected<_Ty, _Uty>(in_place, _Value); } else { @@ -976,6 +980,8 @@ public: constexpr auto transform_error(_Fn&& _Func) && { using _Uty = remove_cv_t>; + static_assert(_Check_unexpected_argument<_Uty>::value); + if (_Has_value) { return expected<_Ty, _Uty>(in_place, _STD move(_Value)); } else { @@ -989,6 +995,8 @@ public: constexpr auto transform_error(_Fn&& _Func) const&& { using _Uty = remove_cv_t>; + static_assert(_Check_unexpected_argument<_Uty>::value); + if (_Has_value) { return expected<_Ty, _Uty>(in_place, _STD move(_Value)); } else { @@ -1003,7 +1011,7 @@ public: requires (!is_void_v<_Uty>) _NODISCARD_FRIEND constexpr bool operator==(const expected& _Left, const expected<_Uty, _UErr>& _Right) noexcept( noexcept(_Fake_copy_init(_Left._Value == *_Right)) && noexcept( - _Fake_copy_init(_Left._Unexpected == _Right.error()))) { // strengthened + _Fake_copy_init(_Left._Unexpected == _Right.error()))) /* strengthened */ { if (_Left._Has_value != _Right.has_value()) { return false; } else if (_Left._Has_value) { @@ -1015,7 +1023,7 @@ public: template _NODISCARD_FRIEND constexpr bool operator==(const expected& _Left, const _Uty& _Right) noexcept( - noexcept(static_cast(_Left._Value == _Right))) { // strengthened + noexcept(static_cast(_Left._Value == _Right))) /* strengthened */ { if (_Left._Has_value) { return static_cast(_Left._Value == _Right); } else { @@ -1025,7 +1033,7 @@ public: template _NODISCARD_FRIEND constexpr bool operator==(const expected& _Left, const unexpected<_UErr>& _Right) noexcept( - noexcept(static_cast(_Left._Unexpected == _Right.error()))) { // strengthened + noexcept(static_cast(_Left._Unexpected == _Right.error()))) /* strengthened */ { if (_Left._Has_value) { return false; } else { @@ -1037,18 +1045,18 @@ private: // These overloads force copy elision from the invoke call into _Value template constexpr expected(_Construct_expected_from_invoke_result_tag, _Fn&& _Func, _Ux&& _Arg) noexcept( - is_nothrow_constructible_v<_Ty, invoke_result_t<_Fn, _Ux>>) + noexcept(_Ty(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))))) : _Value(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))), _Has_value{true} {} // For when transform is called on an expected template constexpr expected(_Construct_expected_from_invoke_result_tag, _Fn&& _Func) noexcept( - is_nothrow_constructible_v<_Ty, invoke_result_t<_Fn>>) - : _Value(_STD invoke(_STD forward<_Fn>(_Func))), _Has_value{true} {} + noexcept(_Ty(_STD forward<_Fn>(_Func)()))) + : _Value(_STD forward<_Fn>(_Func)()), _Has_value{true} {} template constexpr expected(_Construct_expected_from_invoke_result_tag, unexpect_t, _Fn&& _Func, _Ux&& _Arg) noexcept( - is_nothrow_constructible_v<_Err, invoke_result_t<_Fn, _Ux>>) + noexcept(_Err(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))))) : _Unexpected(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))), _Has_value{false} {} @@ -1228,7 +1236,7 @@ public: template requires is_constructible_v<_Err, const _UErr&> && is_assignable_v<_Err&, const _UErr&> constexpr expected& operator=(const unexpected<_UErr>& _Other) noexcept( - is_nothrow_constructible_v<_Err, const _UErr&>&& is_nothrow_assignable_v<_Err&, const _UErr&>) { // strengthened + is_nothrow_constructible_v<_Err, const _UErr&>&& is_nothrow_assignable_v<_Err&, const _UErr&>) /* strengthened */ { if (_Has_value) { _STD construct_at(_STD addressof(_Unexpected), _Other._Unexpected); _Has_value = false; @@ -1242,7 +1250,7 @@ public: template requires is_constructible_v<_Err, _UErr> && is_assignable_v<_Err&, _UErr> constexpr expected& operator=(unexpected<_UErr>&& _Other) noexcept( - is_nothrow_constructible_v<_Err, _UErr>&& is_nothrow_assignable_v<_Err&, _UErr>) { // strengthened + is_nothrow_constructible_v<_Err, _UErr>&& is_nothrow_assignable_v<_Err&, _UErr>) /* strengthened */ { if (_Has_value) { _STD construct_at(_STD addressof(_Unexpected), _STD move(_Other._Unexpected)); _Has_value = false; @@ -1365,7 +1373,7 @@ public: template _NODISCARD constexpr _Err error_or(_Uty&& _Other) const& noexcept( - is_nothrow_copy_constructible_v<_Err>&& is_nothrow_convertible_v<_Uty, _Err>) { // strengthened + is_nothrow_copy_constructible_v<_Err>&& is_nothrow_convertible_v<_Uty, _Err>) /* strengthened */ { static_assert( is_copy_constructible_v<_Err>, "is_copy_constructible_v must be true. (N4928 [expected.void.obs]/9)"); static_assert( @@ -1380,7 +1388,7 @@ public: template _NODISCARD constexpr _Err error_or(_Uty&& _Other) && noexcept( - is_nothrow_move_constructible_v<_Err>&& is_nothrow_convertible_v<_Uty, _Err>) { // strengthened + is_nothrow_move_constructible_v<_Err>&& is_nothrow_convertible_v<_Uty, _Err>) /* strengthened */ { static_assert( is_move_constructible_v<_Err>, "is_move_constructible_v must be true. (N4928 [expected.void.obs]/11)"); static_assert( @@ -1651,7 +1659,7 @@ public: template requires is_void_v<_Uty> _NODISCARD_FRIEND constexpr bool operator==(const expected& _Left, const expected<_Uty, _UErr>& _Right) noexcept( - noexcept(static_cast(_Left._Unexpected == _Right.error()))) { // strengthened + noexcept(static_cast(_Left._Unexpected == _Right.error()))) /* strengthened */ { if (_Left._Has_value != _Right.has_value()) { return false; } else { @@ -1661,7 +1669,7 @@ public: template _NODISCARD_FRIEND constexpr bool operator==(const expected& _Left, const unexpected<_UErr>& _Right) noexcept( - noexcept(static_cast(_Left._Unexpected == _Right.error()))) { // strengthened + noexcept(static_cast(_Left._Unexpected == _Right.error()))) /* strengthened */ { if (_Left._Has_value) { return false; } else { From cc7436f68dc94ac766b235733758483cef868884 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Wed, 1 Feb 2023 09:45:49 +0000 Subject: [PATCH 35/50] Fix noexcept specifications --- stl/inc/expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/expected b/stl/inc/expected index cfd2125afb2..dcd82401ab2 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -1680,7 +1680,7 @@ public: private: template constexpr expected(_Construct_expected_from_invoke_result_tag, unexpect_t, _Fn&& _Func, _Ux&& _Arg) noexcept( - is_nothrow_constructible_v<_Err, invoke_result_t<_Fn, _Ux>>) + noexcept(_Err(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))))) : _Unexpected(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))), _Has_value{false} {} [[noreturn]] void _Throw_bad_expected_access_lv() const { From 211ec583ec8204a3984b95d0a4e9a0e5448bfc82 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Wed, 1 Feb 2023 09:50:08 +0000 Subject: [PATCH 36/50] Guard temporary materialisation bugs --- .../test.cpp | 71 +++++++++++++------ 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp index 4579ba6188e..67e0de1bc9f 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -8,6 +8,28 @@ using namespace std; +namespace detail { + static constexpr bool permissive() { + return false; + } + + template + struct DependentBase { + static constexpr bool permissive() { + return true; + } + }; + + template + struct Derived : DependentBase { + static constexpr bool test() { + return permissive(); + } + }; +} // namespace detail + +constexpr bool is_permissive = detail::Derived::test(); + enum class IsNothrowConstructible : bool { Not, Yes }; enum class IsNothrowConvertible : bool { Not, Yes }; @@ -117,16 +139,18 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { assert(result.error() == 22); } } - { - decltype(auto) result = forward(engaged).transform(immov); - static_assert(is_same_v>); - assert(result->v == 88); - } - { - decltype(auto) result = forward(unengaged).transform(immov); - static_assert(is_same_v>); - assert(!result); - assert(result.error() == 22); + if constexpr (!is_permissive) { // TRANSITION, VSO-1734935 + { + decltype(auto) result = forward(engaged).transform(immov); + static_assert(is_same_v>); + assert(result->v == 88); + } + { + decltype(auto) result = forward(unengaged).transform(immov); + static_assert(is_same_v>); + assert(!result); + assert(result.error() == 22); + } } { decltype(auto) result = forward(engaged).transform(to_void); @@ -171,19 +195,24 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { assert(!result); assert(result.error() == 66); } - { - decltype(auto) result = forward(engaged).transform_error(immov); - static_assert(is_same_v>); - if constexpr (!is_void_v) { - assert(result->x == 11); + + if constexpr (!is_permissive) { // TRANSITION, VSO-1734935 + { + { + decltype(auto) result = forward(engaged).transform_error(immov); + static_assert(is_same_v>); + if constexpr (!is_void_v) { + assert(result->x == 11); + } + } + { + decltype(auto) result = forward(unengaged).transform_error(immov); + static_assert(is_same_v>); + assert(!result); + assert(result.error().v == 88); + } } } - { - decltype(auto) result = forward(unengaged).transform_error(immov); - static_assert(is_same_v>); - assert(!result); - assert(result.error().v == 88); - } const auto to_expected_thingy = [](auto...) { if constexpr (is_void_v) { From ef5a1160863dd72699cb258b5aa39220599a7849 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Wed, 1 Feb 2023 10:36:37 +0000 Subject: [PATCH 37/50] Improve transform and transform_error diagnostics --- stl/inc/expected | 168 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 162 insertions(+), 6 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index dcd82401ab2..b0b32ba297c 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -164,8 +164,15 @@ struct _Construct_expected_from_invoke_result_tag { explicit _Construct_expected_from_invoke_result_tag() = default; }; -_EXPORT_STD template -class expected { +template +concept _Is_invoke_constructible = requires(_Fn&& _Func, _Tys&&... _Vals) { + remove_cvref_t>( + _STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Tys>(_Vals)...)); + }; + + +template +struct _Check_expected_argument : true_type { static_assert(!is_reference_v<_Ty>, "T must not be a reference type. (N4910 [expected.object.general]/2)"); static_assert(!is_function_v<_Ty>, "T must not be a function type. (N4910 [expected.object.general]/2)"); static_assert(!is_same_v, in_place_t>, @@ -174,7 +181,11 @@ class expected { "T must not be (possibly cv-qualified) unexpect_t. (N4910 [expected.object.general]/2)"); static_assert(!_Is_specialization_v, unexpected>, "T must not be a (possibly cv-qualified) specialization of unexpected. (N4910 [expected.object.general]/2)"); +}; +_EXPORT_STD template +class expected { + static_assert(_Check_expected_argument<_Ty>::value); static_assert(_Check_unexpected_argument<_Err>::value); template @@ -437,7 +448,8 @@ public: && (is_nothrow_constructible_v<_Err, const _UErr&> || is_nothrow_move_constructible_v<_Ty> || is_nothrow_move_constructible_v<_Err>) ) constexpr expected& operator=(const unexpected<_UErr>& _Other) noexcept( - is_nothrow_constructible_v<_Err, const _UErr&>&& is_nothrow_assignable_v<_Err&, const _UErr&>) /* strengthened */ { + is_nothrow_constructible_v<_Err, const _UErr&>&& + is_nothrow_assignable_v<_Err&, const _UErr&>) /* strengthened */ { if (_Has_value) { _Reinit_expected(_Unexpected, _Value, _Other._Unexpected); _Has_value = false; @@ -876,8 +888,18 @@ public: template requires is_copy_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) & { + static_assert(invocable<_Fn, _Ty&>, "expected::transform(F) requires that F is invocable with T. " + "(N4928 [expected.object.monadic]/19)"); using _Uty = remove_cv_t>; + if constexpr (!is_void_v<_Uty>) { + static_assert(_Is_invoke_constructible<_Fn, _Ty&>, + "expected::transform(F) requires that the return type of F is constructible with the result of " + "invoking f. " + "(N4928 [expected.object.monadic]/19)"); + } + static_assert(_Check_expected_argument<_Uty>::value); + if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func), _Value); @@ -894,8 +916,18 @@ public: template requires is_copy_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) const& { + static_assert(invocable<_Fn, const _Ty&>, "expected::transform(F) requires that F is invocable with T. " + "(N4928 [expected.object.monadic]/19)"); using _Uty = remove_cv_t>; + if constexpr (!is_void_v<_Uty>) { + static_assert(_Is_invoke_constructible<_Fn, const _Ty&>, + "expected::transform(F) requires that the return type of F is constructible with the result of " + "invoking f. " + "(N4928 [expected.object.monadic]/19)"); + } + static_assert(_Check_expected_argument<_Uty>::value); + if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func), _Value); @@ -912,8 +944,18 @@ public: template requires is_move_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) && { + static_assert(invocable<_Fn, _Ty>, "expected::transform(F) requires that F is invocable with T. " + "(N4928 [expected.object.monadic]/23)"); using _Uty = remove_cv_t>; + if constexpr (!is_void_v<_Uty>) { + static_assert(_Is_invoke_constructible<_Fn, _Ty>, + "expected::transform(F) requires that the return type of F is constructible with the result of " + "invoking f. " + "(N4928 [expected.object.monadic]/23)"); + } + static_assert(_Check_expected_argument<_Uty>::value); + if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Value)); @@ -930,8 +972,18 @@ public: template requires is_move_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) const&& { + static_assert(invocable<_Fn, const _Ty>, "expected::transform(F) requires that F is invocable with T. " + "(N4928 [expected.object.monadic]/23)"); using _Uty = remove_cv_t>; + if constexpr (!is_void_v<_Uty>) { + static_assert(_Is_invoke_constructible<_Fn, const _Ty>, + "expected::transform(F) requires that the return type of F is constructible with the result of " + "invoking f. " + "(N4928 [expected.object.monadic]/23)"); + } + static_assert(_Check_expected_argument<_Uty>::value); + if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Value)); @@ -948,7 +1000,13 @@ public: template requires is_copy_constructible_v<_Ty> constexpr auto transform_error(_Fn&& _Func) & { + static_assert(invocable<_Fn, _Err&>, "expected::transform_error(F) requires that F is invocable with E. " + "(N4928 [expected.object.monadic]/27)"); using _Uty = remove_cv_t>; + static_assert(_Is_invoke_constructible<_Fn, _Err&>, + "expected::transform_error(F) requires that the return type of F is constructible with the result of " + "invoking f. " + "(N4928 [expected.object.monadic]/27)"); static_assert(_Check_unexpected_argument<_Uty>::value); @@ -963,7 +1021,14 @@ public: template requires is_copy_constructible_v<_Ty> constexpr auto transform_error(_Fn&& _Func) const& { + static_assert(invocable<_Fn, const _Err&>, + "expected::transform_error(F) requires that F is invocable with E. " + "(N4928 [expected.object.monadic]/27)"); using _Uty = remove_cv_t>; + static_assert(_Is_invoke_constructible<_Fn, const _Err&>, + "expected::transform_error(F) requires that the return type of F is constructible with the result of " + "invoking f. " + "(N4928 [expected.object.monadic]/27)"); static_assert(_Check_unexpected_argument<_Uty>::value); @@ -978,7 +1043,13 @@ public: template requires is_move_constructible_v<_Ty> constexpr auto transform_error(_Fn&& _Func) && { + static_assert(invocable<_Fn, _Err>, "expected::transform_error(F) requires that F is invocable with E. " + "(N4928 [expected.object.monadic]/31)"); using _Uty = remove_cv_t>; + static_assert(_Is_invoke_constructible<_Fn, _Err>, + "expected::transform_error(F) requires that the return type of F is constructible with the result of " + "invoking f. " + "(N4928 [expected.object.monadic]/31)"); static_assert(_Check_unexpected_argument<_Uty>::value); @@ -993,7 +1064,14 @@ public: template requires is_move_constructible_v<_Ty> constexpr auto transform_error(_Fn&& _Func) const&& { + static_assert(invocable<_Fn, const _Err>, + "expected::transform_error(F) requires that F is invocable with E. " + "(N4928 [expected.object.monadic]/31)"); using _Uty = remove_cv_t>; + static_assert(_Is_invoke_constructible<_Fn, const _Err>, + "expected::transform_error(F) requires that the return type of F is constructible with the result of " + "invoking f. " + "(N4928 [expected.object.monadic]/31)"); static_assert(_Check_unexpected_argument<_Uty>::value); @@ -1236,7 +1314,8 @@ public: template requires is_constructible_v<_Err, const _UErr&> && is_assignable_v<_Err&, const _UErr&> constexpr expected& operator=(const unexpected<_UErr>& _Other) noexcept( - is_nothrow_constructible_v<_Err, const _UErr&>&& is_nothrow_assignable_v<_Err&, const _UErr&>) /* strengthened */ { + is_nothrow_constructible_v<_Err, const _UErr&>&& + is_nothrow_assignable_v<_Err&, const _UErr&>) /* strengthened */ { if (_Has_value) { _STD construct_at(_STD addressof(_Unexpected), _Other._Unexpected); _Has_value = false; @@ -1542,8 +1621,18 @@ public: template requires is_copy_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) & { + static_assert(invocable<_Fn>, "expected::transform(F) requires that F is invocable with no arguments. " + "(N4928 [expected.void.monadic]/17)"); using _Uty = remove_cv_t>; + if constexpr (!is_void_v<_Uty>) { + static_assert(_Is_invoke_constructible<_Fn>, + "expected::transform(F) requires that the return type of F is constructible with the result of " + "invoking f. " + "(N4928 [expected.object.monadic]/17)"); + } + static_assert(_Check_expected_argument<_Uty>::value); + if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func)); @@ -1559,8 +1648,18 @@ public: template requires is_copy_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) const& { + static_assert(invocable<_Fn>, "expected::transform(F) requires that F is invocable with no arguments. " + "(N4928 [expected.void.monadic]/17)"); using _Uty = remove_cv_t>; + if constexpr (!is_void_v<_Uty>) { + static_assert(_Is_invoke_constructible<_Fn>, + "expected::transform(F) requires that the return type of F is constructible with the result of " + "invoking f. " + "(N4928 [expected.object.monadic]/17)"); + } + static_assert(_Check_expected_argument<_Uty>::value); + if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func)); @@ -1576,8 +1675,18 @@ public: template requires is_move_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) && { + static_assert(invocable<_Fn>, "expected::transform(F) requires that F is invocable with no arguments. " + "(N4928 [expected.void.monadic]/21)"); using _Uty = remove_cv_t>; + if constexpr (!is_void_v<_Uty>) { + static_assert(_Is_invoke_constructible<_Fn>, + "expected::transform(F) requires that the return type of F is constructible with the result of " + "invoking f. " + "(N4928 [expected.object.monadic]/21)"); + } + static_assert(_Check_expected_argument<_Uty>::value); + if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func)); @@ -1593,8 +1702,18 @@ public: template requires is_move_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) const&& { + static_assert(invocable<_Fn>, "expected::transform(F) requires that F is invocable with no arguments. " + "(N4928 [expected.void.monadic]/21)"); using _Uty = remove_cv_t>; + if constexpr (!is_void_v<_Uty>) { + static_assert(_Is_invoke_constructible<_Fn>, + "expected::transform(F) requires that the return type of F is constructible with the result of " + "invoking f. " + "(N4928 [expected.object.monadic]/21)"); + } + static_assert(_Check_expected_argument<_Uty>::value); + if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func)); @@ -1609,7 +1728,16 @@ public: template constexpr auto transform_error(_Fn&& _Func) & { + static_assert(invocable<_Fn, _Err&>, + "expected::transform_error(F) requires that F is invocable with E. " + "(N4928 [expected.void.monadic]/24)"); using _Uty = remove_cv_t>; + static_assert(_Is_invoke_constructible<_Fn, _Err&>, "expected::transform_error(F) requires that the " + "return type of F is constructible with the result of " + "invoking f. " + "(N4928 [expected.void.monadic]/24)"); + + static_assert(_Check_unexpected_argument<_Uty>::value); if (_Has_value) { return expected<_Ty, _Uty>(); @@ -1621,7 +1749,17 @@ public: template constexpr auto transform_error(_Fn&& _Func) const& { + static_assert(invocable<_Fn, const _Err&>, + "expected::transform_error(F) requires that F is invocable with E. " + "(N4928 [expected.void.monadic]/24)"); using _Uty = remove_cv_t>; + static_assert(_Is_invoke_constructible<_Fn, const _Err&>, + "expected::transform_error(F) requires that the " + "return type of F is constructible with the result of " + "invoking f. " + "(N4928 [expected.void.monadic]/24)"); + + static_assert(_Check_unexpected_argument<_Uty>::value); if (_Has_value) { return expected<_Ty, _Uty>(); @@ -1633,7 +1771,15 @@ public: template constexpr auto transform_error(_Fn&& _Func) && { - using _Uty = remove_cv_t>; + static_assert(invocable<_Fn, _Err>, "expected::transform_error(F) requires that F is invocable with E. " + "(N4928 [expected.void.monadic]/27)"); + using _Uty = remove_cv_t>; + static_assert(_Is_invoke_constructible<_Fn, _Err>, "expected::transform_error(F) requires that the " + "return type of F is constructible with the result of " + "invoking f. " + "(N4928 [expected.void.monadic]/27)"); + + static_assert(_Check_unexpected_argument<_Uty>::value); if (_Has_value) { return expected<_Ty, _Uty>(); @@ -1645,7 +1791,17 @@ public: template constexpr auto transform_error(_Fn&& _Func) const&& { - using _Uty = remove_cv_t>; + static_assert(invocable<_Fn, const _Err>, + "expected::transform_error(F) requires that F is invocable with E. " + "(N4928 [expected.void.monadic]/24)"); + using _Uty = remove_cv_t>; + static_assert(_Is_invoke_constructible<_Fn, const _Err>, + "expected::transform_error(F) requires that the " + "return type of F is constructible with the result of " + "invoking f. " + "(N4928 [expected.void.monadic]/24)"); + + static_assert(_Check_unexpected_argument<_Uty>::value); if (_Has_value) { return expected<_Ty, _Uty>(); From 5a9e4d42f2f809cb2488a1bbb6b360b8ec040f96 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Thu, 2 Feb 2023 01:37:59 -0800 Subject: [PATCH 38/50] Casey's review comments --- stl/inc/expected | 49 +++++++++---------- tests/libcxx/expected_results.txt | 2 + tests/libcxx/skipped_tests.txt | 4 +- .../test.cpp | 32 ++++++------ 4 files changed, 43 insertions(+), 44 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index b0b32ba297c..ac96bfa15e1 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -30,12 +30,12 @@ class unexpected; template struct _Check_unexpected_argument : true_type { - static_assert(is_object_v<_Err>, "E must be an object type. (N4910 [expected.un.object.general]/1)"); - static_assert(!is_array_v<_Err>, "E must not be an array type. (N4910 [expected.un.object.general]/1)"); - static_assert(!is_const_v<_Err>, "E must not be const. (N4910 [expected.un.object.general]/1)"); - static_assert(!is_volatile_v<_Err>, "E must not be volatile. (N4910 [expected.un.object.general]/1)"); + static_assert(is_object_v<_Err>, "E must be an object type. (N4928 [expected.un.general]/2)"); + static_assert(!is_array_v<_Err>, "E must not be an array type. (N4928 [expected.un.general]/2)"); + static_assert(!is_const_v<_Err>, "E must not be const. (N4928 [expected.un.general]/2)"); + static_assert(!is_volatile_v<_Err>, "E must not be volatile. (N4928 [expected.un.general]/2)"); static_assert(!_Is_specialization_v<_Err, unexpected>, - "E must not be a specialization of unexpected. (N4910 [expected.un.object.general]/1)"); + "E must not be a specialization of unexpected. (N4928 [expected.un.general]/2)"); }; // [expected.un.general] @@ -47,8 +47,7 @@ class unexpected { friend class expected; public: - // [expected.un.ctor] - + // [expected.un.cons] template requires (!is_same_v, unexpected> && !is_same_v, in_place_t> && is_constructible_v<_Err, _UError>) @@ -170,17 +169,17 @@ concept _Is_invoke_constructible = requires(_Fn&& _Func, _Tys&&... _Vals) { _STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Tys>(_Vals)...)); }; - template struct _Check_expected_argument : true_type { - static_assert(!is_reference_v<_Ty>, "T must not be a reference type. (N4910 [expected.object.general]/2)"); - static_assert(!is_function_v<_Ty>, "T must not be a function type. (N4910 [expected.object.general]/2)"); + static_assert(!is_reference_v<_Ty>, "T must not be a reference type. (N4928 [expected.object.general]/2)"); + static_assert(!is_function_v<_Ty>, "T must not be a function type. (N4928 [expected.object.general]/2)"); + static_assert(!is_array_v<_Ty>, "T must not be an array type. (N4928 [expected.object.general]/2)"); static_assert(!is_same_v, in_place_t>, - "T must not be (possibly cv-qualified) in_place_t. (N4910 [expected.object.general]/2)"); + "T must not be (possibly cv-qualified) in_place_t. (N4928 [expected.object.general]/2)"); static_assert(!is_same_v, unexpect_t>, - "T must not be (possibly cv-qualified) unexpect_t. (N4910 [expected.object.general]/2)"); + "T must not be (possibly cv-qualified) unexpect_t. (N4928 [expected.object.general]/2)"); static_assert(!_Is_specialization_v, unexpected>, - "T must not be a (possibly cv-qualified) specialization of unexpected. (N4910 [expected.object.general]/2)"); + "T must not be a (possibly cv-qualified) specialization of unexpected. (N4928 [expected.object.general]/2)"); }; _EXPORT_STD template @@ -199,7 +198,7 @@ public: template using rebind = expected<_Uty, error_type>; - // [expected.object.ctor] + // [expected.object.cons] constexpr expected() noexcept(is_nothrow_default_constructible_v<_Ty>) // strengthened requires is_default_constructible_v<_Ty> : _Value(), _Has_value(true) {} @@ -676,9 +675,9 @@ public: _NODISCARD constexpr _Ty value_or(_Uty&& _Other) const& noexcept( is_nothrow_copy_constructible_v<_Ty>&& is_nothrow_convertible_v<_Uty, _Ty>) /* strengthened */ { static_assert( - is_copy_constructible_v<_Ty>, "is_copy_constructible_v must be true. (N4910 [expected.object.obs]/16)"); + is_copy_constructible_v<_Ty>, "is_copy_constructible_v must be true. (N4928 [expected.object.obs]/16)"); static_assert( - is_convertible_v<_Uty, _Ty>, "is_convertible_v must be true. (N4910 [expected.object.obs]/16)"); + is_convertible_v<_Uty, _Ty>, "is_convertible_v must be true. (N4928 [expected.object.obs]/16)"); if (_Has_value) { return _Value; @@ -690,9 +689,9 @@ public: _NODISCARD constexpr _Ty value_or(_Uty&& _Other) && noexcept( is_nothrow_move_constructible_v<_Ty>&& is_nothrow_convertible_v<_Uty, _Ty>) /* strengthened */ { static_assert( - is_move_constructible_v<_Ty>, "is_move_constructible_v must be true. (N4910 [expected.object.obs]/18)"); + is_move_constructible_v<_Ty>, "is_move_constructible_v must be true. (N4928 [expected.object.obs]/18)"); static_assert( - is_convertible_v<_Uty, _Ty>, "is_convertible_v must be true. (N4910 [expected.object.obs]/18)"); + is_convertible_v<_Uty, _Ty>, "is_convertible_v must be true. (N4928 [expected.object.obs]/18)"); if (_Has_value) { return _STD move(_Value); @@ -732,7 +731,6 @@ public: } // [expected.object.monadic] - template requires is_copy_constructible_v<_Err> constexpr auto and_then(_Fn&& _Func) & { @@ -1084,7 +1082,6 @@ public: } // [expected.object.eq] - template requires (!is_void_v<_Uty>) _NODISCARD_FRIEND constexpr bool operator==(const expected& _Left, const expected<_Uty, _UErr>& _Right) noexcept( @@ -1137,7 +1134,6 @@ private: noexcept(_Err(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))))) : _Unexpected(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))), _Has_value{false} {} - [[noreturn]] void _Throw_bad_expected_access_lv() const { _THROW(bad_expected_access{_Unexpected}); } @@ -1174,7 +1170,7 @@ public: template using rebind = expected<_Uty, error_type>; - // [expected.void.ctor] + // [expected.void.cons] constexpr expected() noexcept : _Has_value(true) {} constexpr expected(const expected& _Other) noexcept(is_nothrow_copy_constructible_v<_Err>) // strengthened @@ -1481,7 +1477,6 @@ public: } // [expected.void.monadic] - template requires is_copy_constructible_v<_Err> constexpr auto and_then(_Fn&& _Func) & { @@ -1584,7 +1579,7 @@ public: template constexpr auto or_else(_Fn&& _Func) && { - using _Uty = remove_cvref_t>; + using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, "expected::or_else(F) requires the return type of F to be a specialization of expected " @@ -1602,7 +1597,7 @@ public: template constexpr auto or_else(_Fn&& _Func) const&& { - using _Uty = remove_cvref_t>; + using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, "expected::or_else(F) requires the return type of F to be a specialization of expected " @@ -1793,13 +1788,13 @@ public: constexpr auto transform_error(_Fn&& _Func) const&& { static_assert(invocable<_Fn, const _Err>, "expected::transform_error(F) requires that F is invocable with E. " - "(N4928 [expected.void.monadic]/24)"); + "(N4928 [expected.void.monadic]/27)"); using _Uty = remove_cv_t>; static_assert(_Is_invoke_constructible<_Fn, const _Err>, "expected::transform_error(F) requires that the " "return type of F is constructible with the result of " "invoking f. " - "(N4928 [expected.void.monadic]/24)"); + "(N4928 [expected.void.monadic]/27)"); static_assert(_Check_unexpected_argument<_Uty>::value); diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index f17c93e9713..46c40f3e7b1 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -75,6 +75,7 @@ std/utilities/charconv/charconv.to.chars/integral.pass.cpp FAIL # libc++ has not implemented P2505R5: "Monadic Functions for std::expected" std/language.support/support.limits/support.limits.general/expected.version.compile.pass.cpp FAIL + # *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX *** # Tracked by VSO-593630 " Enable libcxx filesystem tests" # rapid-cxx-test.hpp uses pragma system_header @@ -233,6 +234,7 @@ std/utilities/format/format.tuple/set_separator.pass.cpp FAIL std/depr/depr.c.headers/uchar_h.compile.pass.cpp FAIL std/strings/c.strings/cuchar.compile.pass.cpp FAIL + # *** MISSING COMPILER FEATURES *** # Nothing here! :-) diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 301c3e62e14..5e88d091a7f 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -73,7 +73,8 @@ utilities\utility\mem.res\mem.res.pool\mem.res.pool.mem\unsync_deallocate_matche utilities\charconv\charconv.to.chars\integral.pass.cpp # libc++ has not implemented P2505R5: "Monadic Functions for std::expected" -std\language.support\support.limits\support.limits.general\expected.version.compile.pass.cpp +language.support\support.limits\support.limits.general\expected.version.compile.pass.cpp + # *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX *** # Tracked by VSO-593630 " Enable libcxx filesystem tests" @@ -233,6 +234,7 @@ utilities\format\format.tuple\set_separator.pass.cpp depr\depr.c.headers\uchar_h.compile.pass.cpp strings\c.strings\cuchar.compile.pass.cpp + # *** MISSING COMPILER FEATURES *** # Nothing here! :-) diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp index 67e0de1bc9f..561fe1fb184 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -99,6 +99,7 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { assert(!result); assert(result.error() == 22); } + if constexpr (!is_void_v) { { decltype(auto) result = forward(engaged).and_then(&Thingy::x); @@ -127,6 +128,7 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { assert(!result); assert(result.error() == 22); } + if constexpr (!is_void_v) { { decltype(auto) result = forward(engaged).transform(&Thingy::member_func); @@ -139,6 +141,7 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { assert(result.error() == 22); } } + if constexpr (!is_permissive) { // TRANSITION, VSO-1734935 { decltype(auto) result = forward(engaged).transform(immov); @@ -152,6 +155,7 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { assert(result.error() == 22); } } + { decltype(auto) result = forward(engaged).transform(to_void); static_assert(is_same_v>); @@ -198,20 +202,18 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { if constexpr (!is_permissive) { // TRANSITION, VSO-1734935 { - { - decltype(auto) result = forward(engaged).transform_error(immov); - static_assert(is_same_v>); - if constexpr (!is_void_v) { - assert(result->x == 11); - } - } - { - decltype(auto) result = forward(unengaged).transform_error(immov); - static_assert(is_same_v>); - assert(!result); - assert(result.error().v == 88); + decltype(auto) result = forward(engaged).transform_error(immov); + static_assert(is_same_v>); + if constexpr (!is_void_v) { + assert(result->x == 11); } } + { + decltype(auto) result = forward(unengaged).transform_error(immov); + static_assert(is_same_v>); + assert(!result); + assert(result.error().v == 88); + } } const auto to_expected_thingy = [](auto...) { @@ -256,11 +258,9 @@ constexpr void test_error_or() { constexpr payload_error_or(const convertible& val) noexcept(conversion_is_noexcept) : _val(val._val + 4) {} constexpr payload_error_or(convertible&& val) noexcept(conversion_is_noexcept) : _val(val._val + 5) {} - [[nodiscard]] constexpr bool operator==(const payload_error_or& right) const noexcept { - return _val == right._val; - } + [[nodiscard]] constexpr bool operator==(const payload_error_or&) const noexcept = default; - int _val = 0; + int _val; }; { // with payload argument From c175fe6cbb11ec5f3c169febd167793a7c7b8293 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Tue, 7 Feb 2023 11:09:03 +0000 Subject: [PATCH 39/50] Add test for error_or({}) --- .../test.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp index 67e0de1bc9f..052ef490cf1 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -248,6 +248,7 @@ constexpr void test_error_or() { constexpr bool should_be_noexcept = construction_is_noexcept && conversion_is_noexcept; struct payload_error_or { + constexpr payload_error_or() noexcept : _val(55) {} constexpr payload_error_or(const int val) noexcept : _val(val) {} constexpr payload_error_or(const payload_error_or& other) noexcept(construction_is_noexcept) : _val(other._val + 2) {} @@ -320,6 +321,20 @@ constexpr void test_error_or() { static_assert(noexcept(move(with_value).error_or(convertible{1})) == should_be_noexcept); static_assert(noexcept(move(const_with_value).error_or(input)) == should_be_noexcept); } + + { // test error_or({}) + using Expected = expected; + + Expected with_error{unexpect, 42}; + const Expected const_with_error{unexpect, 1337}; + Expected with_value{in_place, 42}; + const Expected const_with_value{in_place, 1337}; + + assert(with_error.error_or({}) == 42 + 2); + assert(const_with_error.error_or({}) == 1337 + 2); + assert(with_value.error_or({}) == 55 + 3); + assert(const_with_value.error_or({}) == 55 + 3); + } } constexpr void test_error_or() noexcept { From 57818d66d6f729298429503bcbe826e7acfe7728 Mon Sep 17 00:00:00 2001 From: Sy Brand Date: Tue, 7 Feb 2023 19:59:08 +0000 Subject: [PATCH 40/50] Address video review comments --- stl/inc/expected | 294 ++++++++++++++++++++++------------------------- 1 file changed, 139 insertions(+), 155 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index ac96bfa15e1..e5658dfcd86 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -165,7 +165,7 @@ struct _Construct_expected_from_invoke_result_tag { template concept _Is_invoke_constructible = requires(_Fn&& _Func, _Tys&&... _Vals) { - remove_cvref_t>( + static_cast>>( _STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Tys>(_Vals)...)); }; @@ -737,16 +737,16 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of expected. " + "expected::and_then(F) requires the return type of F to be a specialization of expected. " "(N4928 [expected.object.monadic]/3)."); static_assert(is_same_v, - "expected::and_then(F) requires the error type of the return type of F to be E. " + "expected::and_then(F) requires the error type of the return type of F to be E. " "(N4928 [expected.object.monadic]/3)"); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func), _Value); } else { - return _Uty(unexpect, _Unexpected); + return _Uty{unexpect, _Unexpected}; } } @@ -756,16 +756,16 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of expected. " + "expected::and_then(F) requires the return type of F to be a specialization of expected. " "(N4928 [expected.object.monadic]/3)."); static_assert(is_same_v, - "expected::and_then(F) requires the error type of the return type of F to be E. " + "expected::and_then(F) requires the error type of the return type of F to be E. " "(N4928 [expected.object.monadic]/3)"); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func), _Value); } else { - return _Uty(unexpect, _Unexpected); + return _Uty{unexpect, _Unexpected}; } } @@ -775,10 +775,10 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of expected. " + "expected::and_then(F) requires the return type of F to be a specialization of expected. " "(N4928 [expected.object.monadic]/7)."); static_assert(is_same_v, - "expected::and_then(F) requires the error type of the return type of F to be E. " + "expected::and_then(F) requires the error type of the return type of F to be E. " "(N4928 [expected.object.monadic]/7)"); if (_Has_value) { @@ -794,10 +794,10 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of expected. " + "expected::and_then(F) requires the return type of F to be a specialization of expected. " "(N4928 [expected.object.monadic]/7)."); static_assert(is_same_v, - "expected::and_then(F) requires the error type of the return type of F to be E. " + "expected::and_then(F) requires the error type of the return type of F to be E. " "(N4928 [expected.object.monadic]/7)"); if (_Has_value) { @@ -813,14 +813,14 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::or_else(F) requires the return type of F to be a specialization of expected. " + "expected::or_else(F) requires the return type of F to be a specialization of expected. " "(N4928 [expected.object.monadic]/11)"); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T. " + "expected::or_else(F) requires the value type of the return type of F to be T. " "(N4928 [expected.object.monadic]/11)"); if (_Has_value) { - return _Uty(in_place, _Value); + return _Uty{in_place, _Value}; } else { return _STD invoke(_STD forward<_Fn>(_Func), _Unexpected); } @@ -832,14 +832,14 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::or_else(F) requires the return type of F to be a specialization of expected. " + "expected::or_else(F) requires the return type of F to be a specialization of expected. " "(N4928 [expected.object.monadic]/11)"); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T. " + "expected::or_else(F) requires the value type of the return type of F to be T. " "(N4928 [expected.object.monadic]/11)"); if (_Has_value) { - return _Uty(in_place, _Value); + return _Uty{in_place, _Value}; } else { return _STD invoke(_STD forward<_Fn>(_Func), _Unexpected); } @@ -851,10 +851,10 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::or_else(F) requires the return type of F to be a specialization of expected. " + "expected::or_else(F) requires the return type of F to be a specialization of expected. " "(N4928 [expected.object.monadic]/15)"); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T. " + "expected::or_else(F) requires the value type of the return type of F to be T. " "(N4928 [expected.object.monadic]/15)"); if (_Has_value) { @@ -870,10 +870,10 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::or_else(F) requires the return type of F to be a specialization of expected. " + "expected::or_else(F) requires the return type of F to be a specialization of expected. " "(N4928 [expected.object.monadic]/15)"); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T. " + "expected::or_else(F) requires the value type of the return type of F to be T. " "(N4928 [expected.object.monadic]/15)"); if (_Has_value) { @@ -886,133 +886,128 @@ public: template requires is_copy_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) & { - static_assert(invocable<_Fn, _Ty&>, "expected::transform(F) requires that F is invocable with T. " + static_assert(invocable<_Fn, _Ty&>, "expected::transform(F) requires that F is invocable with T. " "(N4928 [expected.object.monadic]/19)"); using _Uty = remove_cv_t>; if constexpr (!is_void_v<_Uty>) { static_assert(_Is_invoke_constructible<_Fn, _Ty&>, - "expected::transform(F) requires that the return type of F is constructible with the result of " - "invoking f. " - "(N4928 [expected.object.monadic]/19)"); + "expected::transform(F) requires that the return type of F is constructible with the result of " + "invoking f. (N4928 [expected.object.monadic]/19)"); } static_assert(_Check_expected_argument<_Uty>::value); if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func), _Value); - return expected<_Uty, _Err>(); + return expected<_Uty, _Err>{}; } else { - return expected<_Uty, _Err>( - _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _Value); + return expected<_Uty, _Err>{ + _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _Value}; } } else { - return expected<_Uty, _Err>(unexpect, _Unexpected); + return expected<_Uty, _Err>{unexpect, _Unexpected}; } } template requires is_copy_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) const& { - static_assert(invocable<_Fn, const _Ty&>, "expected::transform(F) requires that F is invocable with T. " + static_assert(invocable<_Fn, const _Ty&>, "expected::transform(F) requires that F is invocable with T. " "(N4928 [expected.object.monadic]/19)"); using _Uty = remove_cv_t>; if constexpr (!is_void_v<_Uty>) { static_assert(_Is_invoke_constructible<_Fn, const _Ty&>, - "expected::transform(F) requires that the return type of F is constructible with the result of " - "invoking f. " - "(N4928 [expected.object.monadic]/19)"); + "expected::transform(F) requires that the return type of F is constructible with the result of " + "invoking f. (N4928 [expected.object.monadic]/19)"); } static_assert(_Check_expected_argument<_Uty>::value); if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func), _Value); - return expected<_Uty, _Err>(); + return expected<_Uty, _Err>{}; } else { - return expected<_Uty, _Err>( - _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _Value); + return expected<_Uty, _Err>{ + _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _Value}; } } else { - return expected<_Uty, _Err>(unexpect, _Unexpected); + return expected<_Uty, _Err>{unexpect, _Unexpected}; } } template requires is_move_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) && { - static_assert(invocable<_Fn, _Ty>, "expected::transform(F) requires that F is invocable with T. " + static_assert(invocable<_Fn, _Ty>, "expected::transform(F) requires that F is invocable with T. " "(N4928 [expected.object.monadic]/23)"); using _Uty = remove_cv_t>; if constexpr (!is_void_v<_Uty>) { static_assert(_Is_invoke_constructible<_Fn, _Ty>, - "expected::transform(F) requires that the return type of F is constructible with the result of " - "invoking f. " - "(N4928 [expected.object.monadic]/23)"); + "expected::transform(F) requires that the return type of F is constructible with the result of " + "invoking f. (N4928 [expected.object.monadic]/23)"); } static_assert(_Check_expected_argument<_Uty>::value); if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Value)); - return expected<_Uty, _Err>(); + return expected<_Uty, _Err>{}; } else { - return expected<_Uty, _Err>( - _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _STD move(_Value)); + return expected<_Uty, _Err>{ + _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _STD move(_Value)}; } } else { - return expected<_Uty, _Err>(unexpect, _STD move(_Unexpected)); + return expected<_Uty, _Err>{unexpect, _STD move(_Unexpected)}; } } template requires is_move_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) const&& { - static_assert(invocable<_Fn, const _Ty>, "expected::transform(F) requires that F is invocable with T. " + static_assert(invocable<_Fn, const _Ty>, "expected::transform(F) requires that F is invocable with T. " "(N4928 [expected.object.monadic]/23)"); using _Uty = remove_cv_t>; if constexpr (!is_void_v<_Uty>) { static_assert(_Is_invoke_constructible<_Fn, const _Ty>, - "expected::transform(F) requires that the return type of F is constructible with the result of " - "invoking f. " - "(N4928 [expected.object.monadic]/23)"); + "expected::transform(F) requires that the return type of F is constructible with the result of " + "invoking f. (N4928 [expected.object.monadic]/23)"); } static_assert(_Check_expected_argument<_Uty>::value); if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Value)); - return expected<_Uty, _Err>(); + return expected<_Uty, _Err>{}; } else { - return expected<_Uty, _Err>( - _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _STD move(_Value)); + return expected<_Uty, _Err>{ + _Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _STD move(_Value)}; } } else { - return expected<_Uty, _Err>(unexpect, _STD move(_Unexpected)); + return expected<_Uty, _Err>{unexpect, _STD move(_Unexpected)}; } } template requires is_copy_constructible_v<_Ty> constexpr auto transform_error(_Fn&& _Func) & { - static_assert(invocable<_Fn, _Err&>, "expected::transform_error(F) requires that F is invocable with E. " + static_assert(invocable<_Fn, _Err&>, "expected::transform_error(F) requires that F is invocable with E. " "(N4928 [expected.object.monadic]/27)"); using _Uty = remove_cv_t>; static_assert(_Is_invoke_constructible<_Fn, _Err&>, - "expected::transform_error(F) requires that the return type of F is constructible with the result of " - "invoking f. " - "(N4928 [expected.object.monadic]/27)"); + "expected::transform_error(F) requires that the return type of F is constructible with the result of " + "invoking f. (N4928 [expected.object.monadic]/27)"); static_assert(_Check_unexpected_argument<_Uty>::value); if (_Has_value) { - return expected<_Ty, _Uty>(in_place, _Value); + return expected<_Ty, _Uty>{in_place, _Value}; } else { - return expected<_Ty, _Uty>( - _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), _Unexpected); + return expected<_Ty, _Uty>{ + _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), _Unexpected}; } } @@ -1020,42 +1015,40 @@ public: requires is_copy_constructible_v<_Ty> constexpr auto transform_error(_Fn&& _Func) const& { static_assert(invocable<_Fn, const _Err&>, - "expected::transform_error(F) requires that F is invocable with E. " + "expected::transform_error(F) requires that F is invocable with E. " "(N4928 [expected.object.monadic]/27)"); using _Uty = remove_cv_t>; static_assert(_Is_invoke_constructible<_Fn, const _Err&>, - "expected::transform_error(F) requires that the return type of F is constructible with the result of " - "invoking f. " - "(N4928 [expected.object.monadic]/27)"); + "expected::transform_error(F) requires that the return type of F is constructible with the result of " + "invoking f. (N4928 [expected.object.monadic]/27)"); static_assert(_Check_unexpected_argument<_Uty>::value); if (_Has_value) { - return expected<_Ty, _Uty>(in_place, _Value); + return expected<_Ty, _Uty>{in_place, _Value}; } else { - return expected<_Ty, _Uty>( - _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), _Unexpected); + return expected<_Ty, _Uty>{ + _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), _Unexpected}; } } template requires is_move_constructible_v<_Ty> constexpr auto transform_error(_Fn&& _Func) && { - static_assert(invocable<_Fn, _Err>, "expected::transform_error(F) requires that F is invocable with E. " + static_assert(invocable<_Fn, _Err>, "expected::transform_error(F) requires that F is invocable with E. " "(N4928 [expected.object.monadic]/31)"); using _Uty = remove_cv_t>; static_assert(_Is_invoke_constructible<_Fn, _Err>, - "expected::transform_error(F) requires that the return type of F is constructible with the result of " - "invoking f. " - "(N4928 [expected.object.monadic]/31)"); + "expected::transform_error(F) requires that the return type of F is constructible with the result of " + "invoking f. (N4928 [expected.object.monadic]/31)"); static_assert(_Check_unexpected_argument<_Uty>::value); if (_Has_value) { - return expected<_Ty, _Uty>(in_place, _STD move(_Value)); + return expected<_Ty, _Uty>{in_place, _STD move(_Value)}; } else { - return expected<_Ty, _Uty>(_Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), - _STD move(_Unexpected)); + return expected<_Ty, _Uty>{_Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), + _STD move(_Unexpected)}; } } @@ -1063,21 +1056,20 @@ public: requires is_move_constructible_v<_Ty> constexpr auto transform_error(_Fn&& _Func) const&& { static_assert(invocable<_Fn, const _Err>, - "expected::transform_error(F) requires that F is invocable with E. " + "expected::transform_error(F) requires that F is invocable with E. " "(N4928 [expected.object.monadic]/31)"); using _Uty = remove_cv_t>; static_assert(_Is_invoke_constructible<_Fn, const _Err>, - "expected::transform_error(F) requires that the return type of F is constructible with the result of " - "invoking f. " - "(N4928 [expected.object.monadic]/31)"); + "expected::transform_error(F) requires that the return type of F is constructible with the result of " + "invoking f. (N4928 [expected.object.monadic]/31)"); static_assert(_Check_unexpected_argument<_Uty>::value); if (_Has_value) { - return expected<_Ty, _Uty>(in_place, _STD move(_Value)); + return expected<_Ty, _Uty>{in_place, _STD move(_Value)}; } else { - return expected<_Ty, _Uty>(_Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), - _STD move(_Unexpected)); + return expected<_Ty, _Uty>{_Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), + _STD move(_Unexpected)}; } } @@ -1120,18 +1112,18 @@ private: // These overloads force copy elision from the invoke call into _Value template constexpr expected(_Construct_expected_from_invoke_result_tag, _Fn&& _Func, _Ux&& _Arg) noexcept( - noexcept(_Ty(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))))) + noexcept(static_cast<_Ty>(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))))) : _Value(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))), _Has_value{true} {} - // For when transform is called on an expected + // For when transform is called on an expected and requires calling _Func with no arg template constexpr expected(_Construct_expected_from_invoke_result_tag, _Fn&& _Func) noexcept( - noexcept(_Ty(_STD forward<_Fn>(_Func)()))) + noexcept(static_cast<_Ty>(_STD forward<_Fn>(_Func)()))) : _Value(_STD forward<_Fn>(_Func)()), _Has_value{true} {} template constexpr expected(_Construct_expected_from_invoke_result_tag, unexpect_t, _Fn&& _Func, _Ux&& _Arg) noexcept( - noexcept(_Err(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))))) + noexcept(static_cast<_Err>(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))))) : _Unexpected(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))), _Has_value{false} {} [[noreturn]] void _Throw_bad_expected_access_lv() const { @@ -1483,13 +1475,13 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of expected " + "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.void.monadic]/3."); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func)); } else { - return _Uty(unexpect, _Unexpected); + return _Uty{unexpect, _Unexpected}; } } @@ -1499,13 +1491,13 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of expected " + "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.void.monadic]/3."); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func)); } else { - return _Uty(unexpect, _Unexpected); + return _Uty{unexpect, _Unexpected}; } } @@ -1515,7 +1507,7 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of expected " + "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.void.monadic]/7."); if (_Has_value) { @@ -1531,7 +1523,7 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of expected " + "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.void.monadic]/7."); if (_Has_value) { @@ -1546,10 +1538,10 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::or_else(F) requires the return type of F to be a specialization of expected " + "expected::or_else(F) requires the return type of F to be a specialization of expected " "N4928 [expected.void.monadic]/10."); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T" + "expected::or_else(F) requires the value type of the return type of F to be T" "N4928 [expected.void.monadic]/10."); if (_Has_value) { @@ -1564,10 +1556,10 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::or_else(F) requires the return type of F to be a specialization of expected " + "expected::or_else(F) requires the return type of F to be a specialization of expected " "N4928 [expected.void.monadic]/10."); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T" + "expected::or_else(F) requires the value type of the return type of F to be T" "N4928 [expected.void.monadic]/10."); if (_Has_value) { @@ -1582,10 +1574,10 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::or_else(F) requires the return type of F to be a specialization of expected " + "expected::or_else(F) requires the return type of F to be a specialization of expected " "N4928 [expected.void.monadic]/13."); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T" + "expected::or_else(F) requires the value type of the return type of F to be T" "N4928 [expected.void.monadic]/13."); if (_Has_value) { @@ -1600,10 +1592,10 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::or_else(F) requires the return type of F to be a specialization of expected " + "expected::or_else(F) requires the return type of F to be a specialization of expected " "N4928 [expected.void.monadic]/13."); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T" + "expected::or_else(F) requires the value type of the return type of F to be T" "N4928 [expected.void.monadic]/13."); if (_Has_value) { @@ -1616,193 +1608,185 @@ public: template requires is_copy_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) & { - static_assert(invocable<_Fn>, "expected::transform(F) requires that F is invocable with no arguments. " + static_assert(invocable<_Fn>, "expected::transform(F) requires that F is invocable with no arguments. " "(N4928 [expected.void.monadic]/17)"); using _Uty = remove_cv_t>; if constexpr (!is_void_v<_Uty>) { static_assert(_Is_invoke_constructible<_Fn>, - "expected::transform(F) requires that the return type of F is constructible with the result of " - "invoking f. " - "(N4928 [expected.object.monadic]/17)"); + "expected::transform(F) requires that the return type of F is constructible with the result of " + "invoking f. (N4928 [expected.object.monadic]/17)"); } static_assert(_Check_expected_argument<_Uty>::value); if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func)); - return expected<_Uty, _Err>(); + return expected<_Uty, _Err>{}; } else { - return expected<_Uty, _Err>(_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); + return expected<_Uty, _Err>{_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)}; } } else { - return expected<_Uty, _Err>(unexpect, _Unexpected); + return expected<_Uty, _Err>{unexpect, _Unexpected}; } } template requires is_copy_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) const& { - static_assert(invocable<_Fn>, "expected::transform(F) requires that F is invocable with no arguments. " + static_assert(invocable<_Fn>, "expected::transform(F) requires that F is invocable with no arguments. " "(N4928 [expected.void.monadic]/17)"); using _Uty = remove_cv_t>; if constexpr (!is_void_v<_Uty>) { static_assert(_Is_invoke_constructible<_Fn>, - "expected::transform(F) requires that the return type of F is constructible with the result of " - "invoking f. " - "(N4928 [expected.object.monadic]/17)"); + "expected::transform(F) requires that the return type of F is constructible with the result of " + "invoking f. (N4928 [expected.object.monadic]/17)"); } static_assert(_Check_expected_argument<_Uty>::value); if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func)); - return expected<_Uty, _Err>(); + return expected<_Uty, _Err>{}; } else { - return expected<_Uty, _Err>(_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); + return expected<_Uty, _Err>{_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)}; } } else { - return expected<_Uty, _Err>(unexpect, _Unexpected); + return expected<_Uty, _Err>{unexpect, _Unexpected}; } } template requires is_move_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) && { - static_assert(invocable<_Fn>, "expected::transform(F) requires that F is invocable with no arguments. " + static_assert(invocable<_Fn>, "expected::transform(F) requires that F is invocable with no arguments. " "(N4928 [expected.void.monadic]/21)"); using _Uty = remove_cv_t>; if constexpr (!is_void_v<_Uty>) { static_assert(_Is_invoke_constructible<_Fn>, - "expected::transform(F) requires that the return type of F is constructible with the result of " - "invoking f. " - "(N4928 [expected.object.monadic]/21)"); + "expected::transform(F) requires that the return type of F is constructible with the result of " + "invoking f. (N4928 [expected.object.monadic]/21)"); } static_assert(_Check_expected_argument<_Uty>::value); if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func)); - return expected<_Uty, _Err>(); + return expected<_Uty, _Err>{}; } else { - return expected<_Uty, _Err>(_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); + return expected<_Uty, _Err>{_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)}; } } else { - return expected<_Uty, _Err>(unexpect, _STD move(_Unexpected)); + return expected<_Uty, _Err>{unexpect, _STD move(_Unexpected)}; } } template requires is_move_constructible_v<_Err> constexpr auto transform(_Fn&& _Func) const&& { - static_assert(invocable<_Fn>, "expected::transform(F) requires that F is invocable with no arguments. " + static_assert(invocable<_Fn>, "expected::transform(F) requires that F is invocable with no arguments. " "(N4928 [expected.void.monadic]/21)"); using _Uty = remove_cv_t>; if constexpr (!is_void_v<_Uty>) { static_assert(_Is_invoke_constructible<_Fn>, - "expected::transform(F) requires that the return type of F is constructible with the result of " - "invoking f. " - "(N4928 [expected.object.monadic]/21)"); + "expected::transform(F) requires that the return type of F is constructible with the result of " + "invoking f. (N4928 [expected.object.monadic]/21)"); } static_assert(_Check_expected_argument<_Uty>::value); if (_Has_value) { if constexpr (is_void_v<_Uty>) { _STD invoke(_STD forward<_Fn>(_Func)); - return expected<_Uty, _Err>(); + return expected<_Uty, _Err>{}; } else { - return expected<_Uty, _Err>(_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)); + return expected<_Uty, _Err>{_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)}; } } else { - return expected<_Uty, _Err>(unexpect, _STD move(_Unexpected)); + return expected<_Uty, _Err>{unexpect, _STD move(_Unexpected)}; } } template constexpr auto transform_error(_Fn&& _Func) & { static_assert(invocable<_Fn, _Err&>, - "expected::transform_error(F) requires that F is invocable with E. " + "expected::transform_error(F) requires that F is invocable with E. " "(N4928 [expected.void.monadic]/24)"); using _Uty = remove_cv_t>; - static_assert(_Is_invoke_constructible<_Fn, _Err&>, "expected::transform_error(F) requires that the " + static_assert(_Is_invoke_constructible<_Fn, _Err&>, "expected::transform_error(F) requires that the " "return type of F is constructible with the result of " - "invoking f. " - "(N4928 [expected.void.monadic]/24)"); + "invoking f. (N4928 [expected.void.monadic]/24)"); static_assert(_Check_unexpected_argument<_Uty>::value); if (_Has_value) { - return expected<_Ty, _Uty>(); + return expected<_Ty, _Uty>{}; } else { - return expected<_Ty, _Uty>( - _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), _Unexpected); + return expected<_Ty, _Uty>{ + _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), _Unexpected}; } } template constexpr auto transform_error(_Fn&& _Func) const& { static_assert(invocable<_Fn, const _Err&>, - "expected::transform_error(F) requires that F is invocable with E. " + "expected::transform_error(F) requires that F is invocable with E. " "(N4928 [expected.void.monadic]/24)"); using _Uty = remove_cv_t>; static_assert(_Is_invoke_constructible<_Fn, const _Err&>, - "expected::transform_error(F) requires that the " + "expected::transform_error(F) requires that the " "return type of F is constructible with the result of " - "invoking f. " - "(N4928 [expected.void.monadic]/24)"); + "invoking f. (N4928 [expected.void.monadic]/24)"); static_assert(_Check_unexpected_argument<_Uty>::value); if (_Has_value) { - return expected<_Ty, _Uty>(); + return expected<_Ty, _Uty>{}; } else { - return expected<_Ty, _Uty>( - _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), _Unexpected); + return expected<_Ty, _Uty>{ + _Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), _Unexpected}; } } template constexpr auto transform_error(_Fn&& _Func) && { - static_assert(invocable<_Fn, _Err>, "expected::transform_error(F) requires that F is invocable with E. " + static_assert(invocable<_Fn, _Err>, "expected::transform_error(F) requires that F is invocable with E. " "(N4928 [expected.void.monadic]/27)"); using _Uty = remove_cv_t>; - static_assert(_Is_invoke_constructible<_Fn, _Err>, "expected::transform_error(F) requires that the " + static_assert(_Is_invoke_constructible<_Fn, _Err>, "expected::transform_error(F) requires that the " "return type of F is constructible with the result of " - "invoking f. " - "(N4928 [expected.void.monadic]/27)"); + "invoking f. (N4928 [expected.void.monadic]/27)"); static_assert(_Check_unexpected_argument<_Uty>::value); if (_Has_value) { - return expected<_Ty, _Uty>(); + return expected<_Ty, _Uty>{}; } else { - return expected<_Ty, _Uty>(_Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), - _STD move(_Unexpected)); + return expected<_Ty, _Uty>{_Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), + _STD move(_Unexpected)}; } } template constexpr auto transform_error(_Fn&& _Func) const&& { static_assert(invocable<_Fn, const _Err>, - "expected::transform_error(F) requires that F is invocable with E. " + "expected::transform_error(F) requires that F is invocable with E. " "(N4928 [expected.void.monadic]/27)"); using _Uty = remove_cv_t>; static_assert(_Is_invoke_constructible<_Fn, const _Err>, - "expected::transform_error(F) requires that the " + "expected::transform_error(F) requires that the " "return type of F is constructible with the result of " - "invoking f. " - "(N4928 [expected.void.monadic]/27)"); + "invoking f. (N4928 [expected.void.monadic]/27)"); static_assert(_Check_unexpected_argument<_Uty>::value); if (_Has_value) { - return expected<_Ty, _Uty>(); + return expected<_Ty, _Uty>{}; } else { - return expected<_Ty, _Uty>(_Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), - _STD move(_Unexpected)); + return expected<_Ty, _Uty>{_Construct_expected_from_invoke_result_tag{}, unexpect, _STD forward<_Fn>(_Func), + _STD move(_Unexpected)}; } } From ba9ef72ba37b392e96cbf16daa226e67454bf52b Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 7 Feb 2023 17:46:48 -0800 Subject: [PATCH 41/50] clang-format --- stl/inc/expected | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index e5658dfcd86..880d2e5eebe 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -1613,9 +1613,9 @@ public: using _Uty = remove_cv_t>; if constexpr (!is_void_v<_Uty>) { - static_assert(_Is_invoke_constructible<_Fn>, - "expected::transform(F) requires that the return type of F is constructible with the result of " - "invoking f. (N4928 [expected.object.monadic]/17)"); + static_assert(_Is_invoke_constructible<_Fn>, "expected::transform(F) requires that the return " + "type of F is constructible with the result of " + "invoking f. (N4928 [expected.object.monadic]/17)"); } static_assert(_Check_expected_argument<_Uty>::value); @@ -1639,9 +1639,9 @@ public: using _Uty = remove_cv_t>; if constexpr (!is_void_v<_Uty>) { - static_assert(_Is_invoke_constructible<_Fn>, - "expected::transform(F) requires that the return type of F is constructible with the result of " - "invoking f. (N4928 [expected.object.monadic]/17)"); + static_assert(_Is_invoke_constructible<_Fn>, "expected::transform(F) requires that the return " + "type of F is constructible with the result of " + "invoking f. (N4928 [expected.object.monadic]/17)"); } static_assert(_Check_expected_argument<_Uty>::value); @@ -1665,9 +1665,9 @@ public: using _Uty = remove_cv_t>; if constexpr (!is_void_v<_Uty>) { - static_assert(_Is_invoke_constructible<_Fn>, - "expected::transform(F) requires that the return type of F is constructible with the result of " - "invoking f. (N4928 [expected.object.monadic]/21)"); + static_assert(_Is_invoke_constructible<_Fn>, "expected::transform(F) requires that the return " + "type of F is constructible with the result of " + "invoking f. (N4928 [expected.object.monadic]/21)"); } static_assert(_Check_expected_argument<_Uty>::value); @@ -1691,9 +1691,9 @@ public: using _Uty = remove_cv_t>; if constexpr (!is_void_v<_Uty>) { - static_assert(_Is_invoke_constructible<_Fn>, - "expected::transform(F) requires that the return type of F is constructible with the result of " - "invoking f. (N4928 [expected.object.monadic]/21)"); + static_assert(_Is_invoke_constructible<_Fn>, "expected::transform(F) requires that the return " + "type of F is constructible with the result of " + "invoking f. (N4928 [expected.object.monadic]/21)"); } static_assert(_Check_expected_argument<_Uty>::value); @@ -1752,8 +1752,9 @@ public: template constexpr auto transform_error(_Fn&& _Func) && { - static_assert(invocable<_Fn, _Err>, "expected::transform_error(F) requires that F is invocable with E. " - "(N4928 [expected.void.monadic]/27)"); + static_assert(invocable<_Fn, _Err>, + "expected::transform_error(F) requires that F is invocable with E. " + "(N4928 [expected.void.monadic]/27)"); using _Uty = remove_cv_t>; static_assert(_Is_invoke_constructible<_Fn, _Err>, "expected::transform_error(F) requires that the " "return type of F is constructible with the result of " From cc9376e90870aaa68691e9618dd768df8fd8c13c Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 9 Feb 2023 16:22:14 -0800 Subject: [PATCH 42/50] Add spaces when wrapping string literals. --- stl/inc/expected | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index 880d2e5eebe..4960570a933 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -1541,7 +1541,7 @@ public: "expected::or_else(F) requires the return type of F to be a specialization of expected " "N4928 [expected.void.monadic]/10."); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T" + "expected::or_else(F) requires the value type of the return type of F to be T " "N4928 [expected.void.monadic]/10."); if (_Has_value) { @@ -1559,7 +1559,7 @@ public: "expected::or_else(F) requires the return type of F to be a specialization of expected " "N4928 [expected.void.monadic]/10."); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T" + "expected::or_else(F) requires the value type of the return type of F to be T " "N4928 [expected.void.monadic]/10."); if (_Has_value) { @@ -1577,7 +1577,7 @@ public: "expected::or_else(F) requires the return type of F to be a specialization of expected " "N4928 [expected.void.monadic]/13."); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T" + "expected::or_else(F) requires the value type of the return type of F to be T " "N4928 [expected.void.monadic]/13."); if (_Has_value) { @@ -1595,7 +1595,7 @@ public: "expected::or_else(F) requires the return type of F to be a specialization of expected " "N4928 [expected.void.monadic]/13."); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T" + "expected::or_else(F) requires the value type of the return type of F to be T " "N4928 [expected.void.monadic]/13."); if (_Has_value) { From a502b40013e4379e63f3e2db060862107afe6561 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 9 Feb 2023 16:33:12 -0800 Subject: [PATCH 43/50] Cite [expected.void.monadic]. --- stl/inc/expected | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index 4960570a933..7a7ea342f97 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -1615,7 +1615,7 @@ public: if constexpr (!is_void_v<_Uty>) { static_assert(_Is_invoke_constructible<_Fn>, "expected::transform(F) requires that the return " "type of F is constructible with the result of " - "invoking f. (N4928 [expected.object.monadic]/17)"); + "invoking f. (N4928 [expected.void.monadic]/17)"); } static_assert(_Check_expected_argument<_Uty>::value); @@ -1641,7 +1641,7 @@ public: if constexpr (!is_void_v<_Uty>) { static_assert(_Is_invoke_constructible<_Fn>, "expected::transform(F) requires that the return " "type of F is constructible with the result of " - "invoking f. (N4928 [expected.object.monadic]/17)"); + "invoking f. (N4928 [expected.void.monadic]/17)"); } static_assert(_Check_expected_argument<_Uty>::value); @@ -1667,7 +1667,7 @@ public: if constexpr (!is_void_v<_Uty>) { static_assert(_Is_invoke_constructible<_Fn>, "expected::transform(F) requires that the return " "type of F is constructible with the result of " - "invoking f. (N4928 [expected.object.monadic]/21)"); + "invoking f. (N4928 [expected.void.monadic]/21)"); } static_assert(_Check_expected_argument<_Uty>::value); @@ -1693,7 +1693,7 @@ public: if constexpr (!is_void_v<_Uty>) { static_assert(_Is_invoke_constructible<_Fn>, "expected::transform(F) requires that the return " "type of F is constructible with the result of " - "invoking f. (N4928 [expected.object.monadic]/21)"); + "invoking f. (N4928 [expected.void.monadic]/21)"); } static_assert(_Check_expected_argument<_Uty>::value); From e8e5b8a8a88ad6e28ab55c2284b358b649863409 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 9 Feb 2023 17:38:34 -0800 Subject: [PATCH 44/50] Enforce the error_type mandates for expected::and_then. --- stl/inc/expected | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/stl/inc/expected b/stl/inc/expected index 7a7ea342f97..f21e0fa5309 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -1477,6 +1477,9 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.void.monadic]/3."); + static_assert(is_same_v, + "expected::and_then(F) requires the error type of the return type of F to be E. " + "(N4928 [expected.void.monadic]/3)"); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func)); @@ -1493,6 +1496,9 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.void.monadic]/3."); + static_assert(is_same_v, + "expected::and_then(F) requires the error type of the return type of F to be E. " + "(N4928 [expected.void.monadic]/3)"); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func)); @@ -1509,6 +1515,9 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.void.monadic]/7."); + static_assert(is_same_v, + "expected::and_then(F) requires the error type of the return type of F to be E. " + "(N4928 [expected.void.monadic]/7)"); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func)); @@ -1525,6 +1534,9 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected " "N4928 [expected.void.monadic]/7."); + static_assert(is_same_v, + "expected::and_then(F) requires the error type of the return type of F to be E. " + "(N4928 [expected.void.monadic]/7)"); if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func)); From 0495ad3384bd9db81e5180f81a7d4a69bc3b5de9 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 9 Feb 2023 17:43:15 -0800 Subject: [PATCH 45/50] Throughput-optimize invocation with no args, add comments. --- stl/inc/expected | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index f21e0fa5309..97f7ea075af 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -1118,8 +1118,8 @@ private: // For when transform is called on an expected and requires calling _Func with no arg template constexpr expected(_Construct_expected_from_invoke_result_tag, _Fn&& _Func) noexcept( - noexcept(static_cast<_Ty>(_STD forward<_Fn>(_Func)()))) - : _Value(_STD forward<_Fn>(_Func)()), _Has_value{true} {} + noexcept(static_cast<_Ty>(_STD forward<_Fn>(_Func)()))) // equivalent to invoke() + : _Value(_STD forward<_Fn>(_Func)()), _Has_value{true} {} // equivalent to invoke() template constexpr expected(_Construct_expected_from_invoke_result_tag, unexpect_t, _Fn&& _Func, _Ux&& _Arg) noexcept( @@ -1482,7 +1482,7 @@ public: "(N4928 [expected.void.monadic]/3)"); if (_Has_value) { - return _STD invoke(_STD forward<_Fn>(_Func)); + return _STD forward<_Fn>(_Func)(); // equivalent to invoke() } else { return _Uty{unexpect, _Unexpected}; } @@ -1501,7 +1501,7 @@ public: "(N4928 [expected.void.monadic]/3)"); if (_Has_value) { - return _STD invoke(_STD forward<_Fn>(_Func)); + return _STD forward<_Fn>(_Func)(); // equivalent to invoke() } else { return _Uty{unexpect, _Unexpected}; } @@ -1520,7 +1520,7 @@ public: "(N4928 [expected.void.monadic]/7)"); if (_Has_value) { - return _STD invoke(_STD forward<_Fn>(_Func)); + return _STD forward<_Fn>(_Func)(); // equivalent to invoke() } else { return _Uty(unexpect, _STD move(_Unexpected)); } @@ -1539,7 +1539,7 @@ public: "(N4928 [expected.void.monadic]/7)"); if (_Has_value) { - return _STD invoke(_STD forward<_Fn>(_Func)); + return _STD forward<_Fn>(_Func)(); // equivalent to invoke() } else { return _Uty(unexpect, _STD move(_Unexpected)); } @@ -1633,7 +1633,7 @@ public: if (_Has_value) { if constexpr (is_void_v<_Uty>) { - _STD invoke(_STD forward<_Fn>(_Func)); + _STD forward<_Fn>(_Func)(); // equivalent to invoke() return expected<_Uty, _Err>{}; } else { return expected<_Uty, _Err>{_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)}; @@ -1659,7 +1659,7 @@ public: if (_Has_value) { if constexpr (is_void_v<_Uty>) { - _STD invoke(_STD forward<_Fn>(_Func)); + _STD forward<_Fn>(_Func)(); // equivalent to invoke() return expected<_Uty, _Err>{}; } else { return expected<_Uty, _Err>{_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)}; @@ -1685,7 +1685,7 @@ public: if (_Has_value) { if constexpr (is_void_v<_Uty>) { - _STD invoke(_STD forward<_Fn>(_Func)); + _STD forward<_Fn>(_Func)(); // equivalent to invoke() return expected<_Uty, _Err>{}; } else { return expected<_Uty, _Err>{_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)}; @@ -1711,7 +1711,7 @@ public: if (_Has_value) { if constexpr (is_void_v<_Uty>) { - _STD invoke(_STD forward<_Fn>(_Func)); + _STD forward<_Fn>(_Func)(); // equivalent to invoke() return expected<_Uty, _Err>{}; } else { return expected<_Uty, _Err>{_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)}; From da08d2c926fd1d5611821f51ec99450f0bb033c2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 9 Feb 2023 17:45:25 -0800 Subject: [PATCH 46/50] BRACES FOR THE BRACE THRONE! All of these _Uty types are specializations of expected. --- stl/inc/expected | 20 +++++++++---------- .../test.cpp | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index 97f7ea075af..c6532499ae7 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -784,7 +784,7 @@ public: if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Value)); } else { - return _Uty(unexpect, _STD move(_Unexpected)); + return _Uty{unexpect, _STD move(_Unexpected)}; } } @@ -803,7 +803,7 @@ public: if (_Has_value) { return _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Value)); } else { - return _Uty(unexpect, _STD move(_Unexpected)); + return _Uty{unexpect, _STD move(_Unexpected)}; } } @@ -858,7 +858,7 @@ public: "(N4928 [expected.object.monadic]/15)"); if (_Has_value) { - return _Uty(in_place, _STD move(_Value)); + return _Uty{in_place, _STD move(_Value)}; } else { return _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Unexpected)); } @@ -877,7 +877,7 @@ public: "(N4928 [expected.object.monadic]/15)"); if (_Has_value) { - return _Uty(in_place, _STD move(_Value)); + return _Uty{in_place, _STD move(_Value)}; } else { return _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Unexpected)); } @@ -1522,7 +1522,7 @@ public: if (_Has_value) { return _STD forward<_Fn>(_Func)(); // equivalent to invoke() } else { - return _Uty(unexpect, _STD move(_Unexpected)); + return _Uty{unexpect, _STD move(_Unexpected)}; } } @@ -1541,7 +1541,7 @@ public: if (_Has_value) { return _STD forward<_Fn>(_Func)(); // equivalent to invoke() } else { - return _Uty(unexpect, _STD move(_Unexpected)); + return _Uty{unexpect, _STD move(_Unexpected)}; } } @@ -1557,7 +1557,7 @@ public: "N4928 [expected.void.monadic]/10."); if (_Has_value) { - return _Uty(); + return _Uty{}; } else { return _STD invoke(_STD forward<_Fn>(_Func), _Unexpected); } @@ -1575,7 +1575,7 @@ public: "N4928 [expected.void.monadic]/10."); if (_Has_value) { - return _Uty(); + return _Uty{}; } else { return _STD invoke(_STD forward<_Fn>(_Func), _Unexpected); } @@ -1593,7 +1593,7 @@ public: "N4928 [expected.void.monadic]/13."); if (_Has_value) { - return _Uty(); + return _Uty{}; } else { return _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Unexpected)); } @@ -1611,7 +1611,7 @@ public: "N4928 [expected.void.monadic]/13."); if (_Has_value) { - return _Uty(); + return _Uty{}; } else { return _STD invoke(_STD forward<_Fn>(_Func), _STD move(_Unexpected)); } diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp index f444384e76e..02870d271d1 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -74,7 +74,7 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { using Val = typename remove_cvref_t::value_type; const auto succeed = [](auto...) { return expected{33}; }; - const auto fail = [](auto...) { return expected(unexpect, 44); }; + const auto fail = [](auto...) { return expected{unexpect, 44}; }; { decltype(auto) result = forward(engaged).and_then(succeed); From 096ace67afa8900d193f412fca799c6fb4dcd482 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 9 Feb 2023 17:58:26 -0800 Subject: [PATCH 47/50] Improve citation consistency. --- stl/inc/expected | 56 ++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index c6532499ae7..c0923301c3b 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -738,7 +738,7 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected. " - "(N4928 [expected.object.monadic]/3)."); + "(N4928 [expected.object.monadic]/3)"); static_assert(is_same_v, "expected::and_then(F) requires the error type of the return type of F to be E. " "(N4928 [expected.object.monadic]/3)"); @@ -757,7 +757,7 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected. " - "(N4928 [expected.object.monadic]/3)."); + "(N4928 [expected.object.monadic]/3)"); static_assert(is_same_v, "expected::and_then(F) requires the error type of the return type of F to be E. " "(N4928 [expected.object.monadic]/3)"); @@ -776,7 +776,7 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected. " - "(N4928 [expected.object.monadic]/7)."); + "(N4928 [expected.object.monadic]/7)"); static_assert(is_same_v, "expected::and_then(F) requires the error type of the return type of F to be E. " "(N4928 [expected.object.monadic]/7)"); @@ -795,7 +795,7 @@ public: static_assert(_Is_specialization_v<_Uty, expected>, "expected::and_then(F) requires the return type of F to be a specialization of expected. " - "(N4928 [expected.object.monadic]/7)."); + "(N4928 [expected.object.monadic]/7)"); static_assert(is_same_v, "expected::and_then(F) requires the error type of the return type of F to be E. " "(N4928 [expected.object.monadic]/7)"); @@ -1475,8 +1475,8 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.void.monadic]/3."); + "expected::and_then(F) requires the return type of F to be a specialization of expected. " + "(N4928 [expected.void.monadic]/3)"); static_assert(is_same_v, "expected::and_then(F) requires the error type of the return type of F to be E. " "(N4928 [expected.void.monadic]/3)"); @@ -1494,8 +1494,8 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.void.monadic]/3."); + "expected::and_then(F) requires the return type of F to be a specialization of expected. " + "(N4928 [expected.void.monadic]/3)"); static_assert(is_same_v, "expected::and_then(F) requires the error type of the return type of F to be E. " "(N4928 [expected.void.monadic]/3)"); @@ -1513,8 +1513,8 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.void.monadic]/7."); + "expected::and_then(F) requires the return type of F to be a specialization of expected. " + "(N4928 [expected.void.monadic]/7)"); static_assert(is_same_v, "expected::and_then(F) requires the error type of the return type of F to be E. " "(N4928 [expected.void.monadic]/7)"); @@ -1532,8 +1532,8 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::and_then(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.void.monadic]/7."); + "expected::and_then(F) requires the return type of F to be a specialization of expected. " + "(N4928 [expected.void.monadic]/7)"); static_assert(is_same_v, "expected::and_then(F) requires the error type of the return type of F to be E. " "(N4928 [expected.void.monadic]/7)"); @@ -1550,11 +1550,11 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::or_else(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.void.monadic]/10."); + "expected::or_else(F) requires the return type of F to be a specialization of expected. " + "(N4928 [expected.void.monadic]/10)"); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T " - "N4928 [expected.void.monadic]/10."); + "expected::or_else(F) requires the value type of the return type of F to be T. " + "(N4928 [expected.void.monadic]/10)"); if (_Has_value) { return _Uty{}; @@ -1568,11 +1568,11 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::or_else(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.void.monadic]/10."); + "expected::or_else(F) requires the return type of F to be a specialization of expected. " + "(N4928 [expected.void.monadic]/10)"); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T " - "N4928 [expected.void.monadic]/10."); + "expected::or_else(F) requires the value type of the return type of F to be T. " + "(N4928 [expected.void.monadic]/10)"); if (_Has_value) { return _Uty{}; @@ -1586,11 +1586,11 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::or_else(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.void.monadic]/13."); + "expected::or_else(F) requires the return type of F to be a specialization of expected. " + "(N4928 [expected.void.monadic]/13)"); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T " - "N4928 [expected.void.monadic]/13."); + "expected::or_else(F) requires the value type of the return type of F to be T. " + "(N4928 [expected.void.monadic]/13)"); if (_Has_value) { return _Uty{}; @@ -1604,11 +1604,11 @@ public: using _Uty = remove_cvref_t>; static_assert(_Is_specialization_v<_Uty, expected>, - "expected::or_else(F) requires the return type of F to be a specialization of expected " - "N4928 [expected.void.monadic]/13."); + "expected::or_else(F) requires the return type of F to be a specialization of expected. " + "(N4928 [expected.void.monadic]/13)"); static_assert(is_same_v, - "expected::or_else(F) requires the value type of the return type of F to be T " - "N4928 [expected.void.monadic]/13."); + "expected::or_else(F) requires the value type of the return type of F to be T. " + "(N4928 [expected.void.monadic]/13)"); if (_Has_value) { return _Uty{}; From 393faff29739f3caa5079157d77a29579252fd15 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 9 Feb 2023 18:18:02 -0800 Subject: [PATCH 48/50] Add assert(result) and assert(!result) for consistency. --- .../tests/P2505R5_monadic_functions_for_std_expected/test.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp index 02870d271d1..5b0fbeb449b 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -109,6 +109,7 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { { decltype(auto) result = forward(unengaged).and_then(&Thingy::x); static_assert(is_same_v>); + assert(!result); assert(result.error() == 22); } } @@ -138,6 +139,7 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { { decltype(auto) result = forward(unengaged).transform(&Thingy::member_func); static_assert(is_same_v>); + assert(!result); assert(result.error() == 22); } } @@ -188,6 +190,7 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { decltype(auto) result = forward(engaged).transform_error(to_thingy).transform_error(&Thingy::member_func); static_assert(is_same_v>); + assert(result); if constexpr (!is_void_v) { assert(result->x == 11); } @@ -204,6 +207,7 @@ constexpr void test_impl(Expected&& engaged, Expected&& unengaged) { { decltype(auto) result = forward(engaged).transform_error(immov); static_assert(is_same_v>); + assert(result); if constexpr (!is_void_v) { assert(result->x == 11); } From 28df789d002b801f70876b167d5d1e535151586c Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 9 Feb 2023 18:44:29 -0800 Subject: [PATCH 49/50] Use a unique value 2000. --- .../test.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp index 5b0fbeb449b..9ce4e74d8ae 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -283,16 +283,16 @@ constexpr void test_error_or() { static_assert(noexcept(move(with_error).error_or(payload_error_or{1})) == construction_is_noexcept); static_assert(noexcept(move(const_with_error).error_or(payload_error_or{1})) == construction_is_noexcept); - const payload_error_or input{2}; + const payload_error_or input{2000}; Expected with_value{in_place, 42}; const Expected const_with_value{in_place, 1337}; assert(with_value.error_or(payload_error_or{1}) == 1 + 3); - assert(const_with_value.error_or(input) == 2 + 2); + assert(const_with_value.error_or(input) == 2000 + 2); static_assert(noexcept(with_value.error_or(payload_error_or{1})) == construction_is_noexcept); static_assert(noexcept(const_with_value.error_or(input)) == construction_is_noexcept); assert(move(with_value).error_or(payload_error_or{1}) == 1 + 3); - assert(move(const_with_value).error_or(input) == 2 + 2); + assert(move(const_with_value).error_or(input) == 2000 + 2); static_assert(noexcept(move(with_value).error_or(payload_error_or{1})) == construction_is_noexcept); static_assert(noexcept(move(const_with_value).error_or(input)) == construction_is_noexcept); } @@ -312,16 +312,16 @@ constexpr void test_error_or() { static_assert(noexcept(move(with_error).error_or(convertible{1})) == should_be_noexcept); static_assert(noexcept(move(const_with_error).error_or(convertible{1})) == should_be_noexcept); - const convertible input{2}; + const convertible input{2000}; Expected with_value{in_place, 42}; const Expected const_with_value{in_place, 1337}; assert(with_value.error_or(convertible{1}) == 1 + 5); - assert(const_with_value.error_or(input) == 2 + 4); + assert(const_with_value.error_or(input) == 2000 + 4); static_assert(noexcept(with_value.error_or(convertible{1})) == should_be_noexcept); static_assert(noexcept(const_with_value.error_or(input)) == should_be_noexcept); assert(move(with_value).error_or(convertible{1}) == 1 + 5); - assert(move(const_with_value).error_or(input) == 2 + 4); + assert(move(const_with_value).error_or(input) == 2000 + 4); static_assert(noexcept(move(with_value).error_or(convertible{1})) == should_be_noexcept); static_assert(noexcept(move(const_with_value).error_or(input)) == should_be_noexcept); } From b08896c51ba0f163e91246b8624c5ae2b944076f Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Thu, 9 Feb 2023 19:32:11 -0800 Subject: [PATCH 50/50] Correct "equivalent to invoke()" comments --- stl/inc/expected | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index c0923301c3b..9d4a583cfd0 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -1118,8 +1118,8 @@ private: // For when transform is called on an expected and requires calling _Func with no arg template constexpr expected(_Construct_expected_from_invoke_result_tag, _Fn&& _Func) noexcept( - noexcept(static_cast<_Ty>(_STD forward<_Fn>(_Func)()))) // equivalent to invoke() - : _Value(_STD forward<_Fn>(_Func)()), _Has_value{true} {} // equivalent to invoke() + noexcept(static_cast<_Ty>(_STD forward<_Fn>(_Func)()))) // f() is equivalent to invoke(f) + : _Value(_STD forward<_Fn>(_Func)()), _Has_value{true} {} // f() is equivalent to invoke(f) template constexpr expected(_Construct_expected_from_invoke_result_tag, unexpect_t, _Fn&& _Func, _Ux&& _Arg) noexcept( @@ -1482,7 +1482,7 @@ public: "(N4928 [expected.void.monadic]/3)"); if (_Has_value) { - return _STD forward<_Fn>(_Func)(); // equivalent to invoke() + return _STD forward<_Fn>(_Func)(); // f() is equivalent to invoke(f) } else { return _Uty{unexpect, _Unexpected}; } @@ -1501,7 +1501,7 @@ public: "(N4928 [expected.void.monadic]/3)"); if (_Has_value) { - return _STD forward<_Fn>(_Func)(); // equivalent to invoke() + return _STD forward<_Fn>(_Func)(); // f() is equivalent to invoke(f) } else { return _Uty{unexpect, _Unexpected}; } @@ -1520,7 +1520,7 @@ public: "(N4928 [expected.void.monadic]/7)"); if (_Has_value) { - return _STD forward<_Fn>(_Func)(); // equivalent to invoke() + return _STD forward<_Fn>(_Func)(); // f() is equivalent to invoke(f) } else { return _Uty{unexpect, _STD move(_Unexpected)}; } @@ -1539,7 +1539,7 @@ public: "(N4928 [expected.void.monadic]/7)"); if (_Has_value) { - return _STD forward<_Fn>(_Func)(); // equivalent to invoke() + return _STD forward<_Fn>(_Func)(); // f() is equivalent to invoke(f) } else { return _Uty{unexpect, _STD move(_Unexpected)}; } @@ -1633,7 +1633,7 @@ public: if (_Has_value) { if constexpr (is_void_v<_Uty>) { - _STD forward<_Fn>(_Func)(); // equivalent to invoke() + _STD forward<_Fn>(_Func)(); // f() is equivalent to invoke(f) return expected<_Uty, _Err>{}; } else { return expected<_Uty, _Err>{_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)}; @@ -1659,7 +1659,7 @@ public: if (_Has_value) { if constexpr (is_void_v<_Uty>) { - _STD forward<_Fn>(_Func)(); // equivalent to invoke() + _STD forward<_Fn>(_Func)(); // f() is equivalent to invoke(f) return expected<_Uty, _Err>{}; } else { return expected<_Uty, _Err>{_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)}; @@ -1685,7 +1685,7 @@ public: if (_Has_value) { if constexpr (is_void_v<_Uty>) { - _STD forward<_Fn>(_Func)(); // equivalent to invoke() + _STD forward<_Fn>(_Func)(); // f() is equivalent to invoke(f) return expected<_Uty, _Err>{}; } else { return expected<_Uty, _Err>{_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)}; @@ -1711,7 +1711,7 @@ public: if (_Has_value) { if constexpr (is_void_v<_Uty>) { - _STD forward<_Fn>(_Func)(); // equivalent to invoke() + _STD forward<_Fn>(_Func)(); // f() is equivalent to invoke(f) return expected<_Uty, _Err>{}; } else { return expected<_Uty, _Err>{_Construct_expected_from_invoke_result_tag{}, _STD forward<_Fn>(_Func)};