From 52b41196e95c242c70e5d06f081176922630bc2c Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Sat, 31 Dec 2022 19:22:29 +0800 Subject: [PATCH 1/3] Also test exception specifications for `promise` --- .../test.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/std/tests/Dev11_0235721_async_and_packaged_task/test.cpp b/tests/std/tests/Dev11_0235721_async_and_packaged_task/test.cpp index 9234c70818b..01f36705656 100644 --- a/tests/std/tests/Dev11_0235721_async_and_packaged_task/test.cpp +++ b/tests/std/tests/Dev11_0235721_async_and_packaged_task/test.cpp @@ -283,6 +283,20 @@ void test_future_shared_future_noexcept() { test_shared_future_noexcept_copy_impl(); } +// Also test the exception specifications of move functions of promise +template +void test_promise_noexcept_impl() { + STATIC_ASSERT(is_nothrow_move_constructible_v>); + STATIC_ASSERT(is_nothrow_move_assignable_v>); + STATIC_ASSERT(is_nothrow_destructible_v>); +} + +void test_promise_noexcept() { + test_promise_noexcept_impl(); + test_promise_noexcept_impl(); + test_promise_noexcept_impl(); +} + // Also test the non-constructibility of future from (future, {}) and (shared_future, {}) template constexpr bool is_constructible_with_trailing_empty_brace_impl = false; @@ -331,5 +345,6 @@ int main() { test_VSO_115515(); test_VSO_272761(); test_future_shared_future_noexcept(); + test_promise_noexcept(); test_no_implicit_brace_construction(); } From bec894673632cff6420832f685642f4c8d601d8c Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Sat, 31 Dec 2022 20:28:20 +0800 Subject: [PATCH 2/3] Also test exception specifications for `packaged_task` --- .../test.cpp | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/std/tests/Dev11_0235721_async_and_packaged_task/test.cpp b/tests/std/tests/Dev11_0235721_async_and_packaged_task/test.cpp index 01f36705656..e60da459b10 100644 --- a/tests/std/tests/Dev11_0235721_async_and_packaged_task/test.cpp +++ b/tests/std/tests/Dev11_0235721_async_and_packaged_task/test.cpp @@ -283,7 +283,7 @@ void test_future_shared_future_noexcept() { test_shared_future_noexcept_copy_impl(); } -// Also test the exception specifications of move functions of promise +// Also test the exception specifications of move functions of promise and packaged_task template void test_promise_noexcept_impl() { STATIC_ASSERT(is_nothrow_move_constructible_v>); @@ -297,6 +297,24 @@ void test_promise_noexcept() { test_promise_noexcept_impl(); } +template +void test_packaged_task_noexcept_impl() { + STATIC_ASSERT(is_nothrow_default_constructible_v>); + STATIC_ASSERT(is_nothrow_move_constructible_v>); + STATIC_ASSERT(is_nothrow_move_assignable_v>); + STATIC_ASSERT(is_nothrow_destructible_v>); +} + +void test_packaged_task_noexcept() { + test_packaged_task_noexcept_impl(); + test_packaged_task_noexcept_impl(); + test_packaged_task_noexcept_impl(); + + test_packaged_task_noexcept_impl(); + test_packaged_task_noexcept_impl(); + test_packaged_task_noexcept_impl(); +} + // Also test the non-constructibility of future from (future, {}) and (shared_future, {}) template constexpr bool is_constructible_with_trailing_empty_brace_impl = false; @@ -346,5 +364,6 @@ int main() { test_VSO_272761(); test_future_shared_future_noexcept(); test_promise_noexcept(); + test_packaged_task_noexcept(); test_no_implicit_brace_construction(); } From fe871f98290b57d32e8fc99f2ca948298022b64b Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Sat, 31 Dec 2022 20:38:02 +0800 Subject: [PATCH 3/3] Defaulted special member functions for `promise` and `packaged_task` --- stl/inc/future | 49 ++++++++++++++++++++----------------------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/stl/inc/future b/stl/inc/future index 2fb20b99691..1ded113078c 100644 --- a/stl/inc/future +++ b/stl/inc/future @@ -290,7 +290,7 @@ public: } // TRANSITION: `_Retrieved` should be assigned before `_Exception` is thrown so that a `future::get` - // that throws a stored exception invalidates the future (N4917 [futures.unique.future]/17) + // that throws a stored exception invalidates the future (N4928 [futures.unique.future]/17) _Retrieved = true; _Maybe_run_deferred_function(_Lock); while (!_Ready) { @@ -361,7 +361,7 @@ public: } _STL_ASSERT(_Exc != nullptr, "promise::set_exception/set_exception_at_thread_exit called with a null " - "std::exception_ptr, which is invalid per N4917 [futures.promise]/20"); + "std::exception_ptr, which is invalid per N4928 [futures.promise]/20"); _Exception = _Exc; _Do_notify(_Lock, _At_thread_exit); } @@ -879,7 +879,7 @@ private: public: static_assert(!is_array_v<_Ty> && is_object_v<_Ty> && is_destructible_v<_Ty>, - "T in future must meet the Cpp17Destructible requirements (N4917 [futures.unique.future]/4)."); + "T in future must meet the Cpp17Destructible requirements (N4928 [futures.unique.future]/4)."); future() = default; @@ -967,7 +967,7 @@ private: public: static_assert(!is_array_v<_Ty> && is_object_v<_Ty> && is_destructible_v<_Ty>, - "T in shared_future must meet the Cpp17Destructible requirements (N4917 [futures.shared.future]/4)."); + "T in shared_future must meet the Cpp17Destructible requirements (N4928 [futures.shared.future]/4)."); shared_future() = default; @@ -1043,27 +1043,21 @@ _NODISCARD inline shared_future future::share() noexcept { template class _Promise { public: - _Promise(_Associated_state<_Ty>* _State_ptr) : _State(_State_ptr, false), _Future_retrieved(false) {} + _Promise(_Associated_state<_Ty>* _State_ptr) noexcept : _State(_State_ptr, false), _Future_retrieved(false) {} - _Promise(_Promise&& _Other) : _State(_STD move(_Other._State)), _Future_retrieved(_Other._Future_retrieved) {} + _Promise(_Promise&&) = default; - _Promise& operator=(_Promise&& _Other) { - _State = _STD move(_Other._State); - _Future_retrieved = _Other._Future_retrieved; - return *this; - } + _Promise& operator=(_Promise&&) = default; - ~_Promise() noexcept {} - - void _Swap(_Promise& _Other) { + void _Swap(_Promise& _Other) noexcept { _State._Swap(_Other._State); _STD swap(_Future_retrieved, _Other._Future_retrieved); } - const _State_manager<_Ty>& _Get_state() const { + const _State_manager<_Ty>& _Get_state() const noexcept { return _State; } - _State_manager<_Ty>& _Get_state() { + _State_manager<_Ty>& _Get_state() noexcept { return _State; } @@ -1092,11 +1086,11 @@ public: return _State.valid(); } - bool _Is_ready() const { + bool _Is_ready() const noexcept { return _State._Is_ready(); } - bool _Is_ready_at_thread_exit() const { + bool _Is_ready_at_thread_exit() const noexcept { return _State._Is_ready_at_thread_exit(); } @@ -1112,14 +1106,14 @@ _EXPORT_STD template class promise { // class that defines an asynchronous provider that holds a value public: static_assert(!is_array_v<_Ty> && is_object_v<_Ty> && is_destructible_v<_Ty>, - "T in promise must meet the Cpp17Destructible requirements (N4917 [futures.promise]/1)."); + "T in promise must meet the Cpp17Destructible requirements (N4928 [futures.promise]/1)."); promise() : _MyPromise(new _Associated_state<_Ty>) {} template promise(allocator_arg_t, const _Alloc& _Al) : _MyPromise(_Make_associated_state<_Ty>(_Al)) {} - promise(promise&& _Other) noexcept : _MyPromise(_STD move(_Other._MyPromise)) {} + promise(promise&&) = default; promise& operator=(promise&& _Other) noexcept { promise(_STD move(_Other)).swap(*this); @@ -1181,7 +1175,7 @@ public: template promise(allocator_arg_t, const _Alloc& _Al) : _MyPromise(_Make_associated_state<_Ty*>(_Al)) {} - promise(promise&& _Other) noexcept : _MyPromise(_STD move(_Other._MyPromise)) {} + promise(promise&&) = default; promise& operator=(promise&& _Other) noexcept { promise(_STD move(_Other)).swap(*this); @@ -1235,7 +1229,7 @@ public: template promise(allocator_arg_t, const _Alloc& _Al) : _MyPromise(_Make_associated_state(_Al)) {} - promise(promise&& _Other) noexcept : _MyPromise(_STD move(_Other._MyPromise)) {} + promise(promise&&) = default; promise& operator=(promise&& _Other) noexcept { promise(_STD move(_Other)).swap(*this); @@ -1316,17 +1310,14 @@ public: using _MyStateManagerType = _State_manager<_Ptype>; using _MyStateType = _Packaged_state<_Ret(_ArgTypes...)>; - packaged_task() noexcept : _MyPromise(0) {} + packaged_task() = default; template , packaged_task>, int> = 0> explicit packaged_task(_Fty2&& _Fnarg) : _MyPromise(new _MyStateType(_STD forward<_Fty2>(_Fnarg))) {} - packaged_task(packaged_task&& _Other) noexcept : _MyPromise(_STD move(_Other._MyPromise)) {} + packaged_task(packaged_task&&) = default; - packaged_task& operator=(packaged_task&& _Other) noexcept { - _MyPromise = _STD move(_Other._MyPromise); - return *this; - } + packaged_task& operator=(packaged_task&&) = default; #if _HAS_FUNCTION_ALLOCATOR_SUPPORT template , packaged_task>, int> = 0> @@ -1387,7 +1378,7 @@ public: packaged_task& operator=(const packaged_task&) = delete; private: - _MyPromiseType _MyPromise; + _MyPromiseType _MyPromise{nullptr}; }; #if _HAS_CXX17