From 66f96bcbf18d8d6c236f369d8416567474933731 Mon Sep 17 00:00:00 2001 From: Dietmar Kuehl Date: Mon, 31 Jan 2022 23:54:51 +0000 Subject: [PATCH 1/6] added set_stopped --- CMakeLists.txt | 28 +++++- README.md | 7 +- include/execution.hpp | 1 + include/p2300/set_stopped.hpp | 59 ++++++++++++ include/p2300/start.hpp | 2 +- test/set_stopped.cpp | 170 ++++++++++++++++++++++++++++++++++ test/start.cpp | 2 +- 7 files changed, 265 insertions(+), 4 deletions(-) create mode 100644 include/p2300/set_stopped.hpp create mode 100644 test/set_stopped.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c32874..15ea4ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,28 @@ +# CMakeLists.txt -*-cmake-*- +# ---------------------------------------------------------------------------- +# Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of +# the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# ---------------------------------------------------------------------------- + cmake_minimum_required(VERSION 3.14.0) project(p2300 VERSION 0.1.0) @@ -35,6 +60,7 @@ list(APPEND test_exposition_only list(APPEND test_components test/operation_state.cpp + test/set_stopped.cpp test/start.cpp test/tag_invoke.cpp ) @@ -43,4 +69,4 @@ add_executable(p2300_test ${test_exposition_only} ${test_components}) target_link_libraries(p2300_test PUBLIC gtest_main) include(GoogleTest) -gtest_discover_tests(p2300_test) \ No newline at end of file +gtest_discover_tests(p2300_test) diff --git a/README.md b/README.md index bb1682a..5b12b38 100644 --- a/README.md +++ b/README.md @@ -15,5 +15,10 @@ can be reported on the [P2300 issue tracker](https://github.com/brycelelbach/wg2 concept operation_state = destructible && is_object_v - && requires(S& s) { { execution::start(s) } noexcept; } + && requires(S& s) { { execution::start(s) } noexcept; } ; + +## Customization Point Overview + +- `set_stopped(auto&& receiver) noexcept -> void` +- `start(auto& state) noexcept -> void` diff --git a/include/execution.hpp b/include/execution.hpp index 21b2ac6..e9beb5b 100644 --- a/include/execution.hpp +++ b/include/execution.hpp @@ -32,6 +32,7 @@ #include #include +#include #include #include diff --git a/include/p2300/set_stopped.hpp b/include/p2300/set_stopped.hpp new file mode 100644 index 0000000..2eb1fed --- /dev/null +++ b/include/p2300/set_stopped.hpp @@ -0,0 +1,59 @@ +// include/p2300/set_stopped.hpp -*-C++-*- +// ---------------------------------------------------------------------------- +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, +// merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// ---------------------------------------------------------------------------- + +#ifndef INCLUDED_INCLUDE_P2300_SET_STOPPED +#define INCLUDED_INCLUDE_P2300_SET_STOPPED + +#include +#include +#include + +// ---------------------------------------------------------------------------- +// [exec.set_stopped] + +namespace std { + namespace _Set_stopped { + class _Cpo { + public: + template + requires nothrow_tag_invocable<_Cpo, _Receiver> + auto operator()(_Receiver&& __receiver) const noexcept -> void + { + std::tag_invoke(*this, std::forward<_Receiver>(__receiver)); + } + }; + } + + namespace execution { + using set_stopped_t = _Set_stopped::_Cpo; + inline namespace _Cpos { + inline constexpr set_stopped_t set_stopped{}; + } + } +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/p2300/start.hpp b/include/p2300/start.hpp index 82e6f5d..cacc4fd 100644 --- a/include/p2300/start.hpp +++ b/include/p2300/start.hpp @@ -41,7 +41,7 @@ namespace std { && std::is_lvalue_reference_v<_OperationState> auto operator()(_OperationState&& __state) const noexcept -> void { - tag_invoke(*this, __state); + std::tag_invoke(*this, __state); } }; } diff --git a/test/set_stopped.cpp b/test/set_stopped.cpp new file mode 100644 index 0000000..554feaa --- /dev/null +++ b/test/set_stopped.cpp @@ -0,0 +1,170 @@ +// test/set_stopped.cpp -*-C++-*- +// ---------------------------------------------------------------------------- +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, +// merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// ---------------------------------------------------------------------------- + +#include "test-config.hpp" +#include P2300_execution +#include P2300_type_traits +#include + +// ---------------------------------------------------------------------------- + +namespace +{ + template + struct rvalue_receiver + { + bool* called; + friend void tag_invoke(std::execution::set_stopped_t, rvalue_receiver&& self) noexcept(Noexcept) { + *self.called = true; + } + }; + + template + struct lvalue_receiver + { + bool* called; + friend void tag_invoke(std::execution::set_stopped_t, lvalue_receiver& self) noexcept(Noexcept) { + *self.called = true; + } + }; + + template + struct const_receiver + { + bool* called; + friend void tag_invoke(std::execution::set_stopped_t, const_receiver const& self) noexcept(Noexcept) { + *self.called = true; + } + }; +} + +// ---------------------------------------------------------------------------- + +TEST(set_stopped, test_classes) +{ + static_assert(std::invocable>); + static_assert(std::invocable>); + static_assert(not std::invocable&>); + static_assert(not std::invocable&>); + static_assert(not std::invocable const&>); + static_assert(not std::invocable const&>); + static_assert(noexcept(tag_invoke(std::execution::set_stopped, std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_stopped, std::declval>()))); + + static_assert(not std::invocable>); + static_assert(not std::invocable>); + static_assert(std::invocable&>); + static_assert(std::invocable&>); + static_assert(not std::invocable const&>); + static_assert(not std::invocable const&>); + static_assert(noexcept(tag_invoke(std::execution::set_stopped, std::declval&>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_stopped, std::declval&>()))); + + static_assert(std::invocable>); + static_assert(std::invocable>); + static_assert(std::invocable&>); + static_assert(std::invocable&>); + static_assert(std::invocable const&>); + static_assert(std::invocable const&>); + static_assert(noexcept(tag_invoke(std::execution::set_stopped, std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_stopped, std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_stopped, std::declval&>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_stopped, std::declval&>()))); + static_assert(noexcept(tag_invoke(std::execution::set_stopped, std::declval const&>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_stopped, std::declval const&>()))); +} + +TEST(set_stopped, rvalue_calls) +{ + static_assert(std::invocable>); + static_assert(not std::invocable>); + static_assert(not std::invocable&>); + static_assert(not std::invocable&>); + static_assert(not std::invocable const&>); + static_assert(not std::invocable const&>); + static_assert(noexcept(std::execution::set_stopped(std::declval>()))); + + bool called{false}; + ASSERT_FALSE(called); + std::execution::set_stopped(rvalue_receiver{&called}); + EXPECT_TRUE(called); + +} + +TEST(set_stopped, lvalue_calls) +{ + static_assert(not std::invocable>); + static_assert(not std::invocable>); + static_assert(std::invocable&>); + static_assert(not std::invocable&>); + static_assert(not std::invocable const&>); + static_assert(not std::invocable const&>); + static_assert(noexcept(std::execution::set_stopped(std::declval&>()))); + + bool called{false}; + lvalue_receiver receiver{&called}; + + ASSERT_FALSE(called); + std::execution::set_stopped(receiver); + EXPECT_TRUE(called); + +} + +TEST(set_stopped, const_calls) +{ + static_assert(std::invocable>); + static_assert(not std::invocable>); + static_assert(std::invocable&>); + static_assert(not std::invocable&>); + static_assert(std::invocable const&>); + static_assert(not std::invocable const&>); + static_assert(noexcept(std::execution::set_stopped(std::declval>()))); + static_assert(noexcept(std::execution::set_stopped(std::declval&>()))); + static_assert(noexcept(std::execution::set_stopped(std::declval const&>()))); + + { + bool called{false}; + + ASSERT_FALSE(called); + std::execution::set_stopped(const_receiver{&called}); + EXPECT_TRUE(called); + } + { + bool called{false}; + const_receiver receiver{&called}; + + ASSERT_FALSE(called); + std::execution::set_stopped(receiver); + EXPECT_TRUE(called); + } + { + bool called{false}; + const_receiver const receiver{&called}; + + ASSERT_FALSE(called); + std::execution::set_stopped(receiver); + EXPECT_TRUE(called); + } +} \ No newline at end of file diff --git a/test/start.cpp b/test/start.cpp index a25dc80..9fd41e6 100644 --- a/test/start.cpp +++ b/test/start.cpp @@ -127,4 +127,4 @@ TEST(start, indestructible_state) EXPECT_EQ(started, 3); indestructible_state::destroy(s); -} \ No newline at end of file +} From 08d0dad855a2ca755b75469d1545267108df942e Mon Sep 17 00:00:00 2001 From: Dietmar Kuehl Date: Sat, 5 Feb 2022 23:22:38 +0000 Subject: [PATCH 2/6] added set_error implementation --- CMakeLists.txt | 1 + README.md | 1 + include/execution.hpp | 1 + include/p2300/set_error.hpp | 54 ++++++++++ test/set_error.cpp | 192 ++++++++++++++++++++++++++++++++++++ 5 files changed, 249 insertions(+) create mode 100644 include/p2300/set_error.hpp create mode 100644 test/set_error.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 15ea4ff..522317f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,7 @@ list(APPEND test_exposition_only list(APPEND test_components test/operation_state.cpp + test/set_error.cpp test/set_stopped.cpp test/start.cpp test/tag_invoke.cpp diff --git a/README.md b/README.md index 5b12b38..9c52dfd 100644 --- a/README.md +++ b/README.md @@ -20,5 +20,6 @@ can be reported on the [P2300 issue tracker](https://github.com/brycelelbach/wg2 ## Customization Point Overview +- `set_error(auto&& receiver, auto&& error) noexcept -> void` - `set_stopped(auto&& receiver) noexcept -> void` - `start(auto& state) noexcept -> void` diff --git a/include/execution.hpp b/include/execution.hpp index e9beb5b..33cec65 100644 --- a/include/execution.hpp +++ b/include/execution.hpp @@ -32,6 +32,7 @@ #include #include +#include #include #include #include diff --git a/include/p2300/set_error.hpp b/include/p2300/set_error.hpp new file mode 100644 index 0000000..7e4ad21 --- /dev/null +++ b/include/p2300/set_error.hpp @@ -0,0 +1,54 @@ +// include/p2300/set_error.hpp -*-C++-*- +// ---------------------------------------------------------------------------- +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, +// merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// ---------------------------------------------------------------------------- + +#ifndef INCLUDED_INCLUDE_P2300_SET_ERROR +#define INCLUDED_INCLUDE_P2300_SET_ERROR + +// ---------------------------------------------------------------------------- + +namespace std { + namespace _Set_error { + class _Cpo { + public: + template + requires nothrow_tag_invocable<_Cpo, _Receiver, _Error> + auto operator()(_Receiver&& __receiver, _Error&& __error) const noexcept -> void + { + std::tag_invoke(*this, std::forward<_Receiver>(__receiver), std::forward<_Error>(__error)); + } + }; + } + + namespace execution { + using set_error_t = _Set_error::_Cpo; + inline namespace _Cpos { + inline constexpr set_error_t set_error{}; + } + } +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/test/set_error.cpp b/test/set_error.cpp new file mode 100644 index 0000000..fa8986c --- /dev/null +++ b/test/set_error.cpp @@ -0,0 +1,192 @@ +// test/set_error.cpp -*-C++-*- +// ---------------------------------------------------------------------------- +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, +// merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// ---------------------------------------------------------------------------- + +#include "test-config.hpp" +#include P2300_execution +#include P2300_type_traits +#include + +// ---------------------------------------------------------------------------- + +namespace +{ + struct error {}; + struct no_error {}; + + template + struct rvalue_receiver + { + error const** called; + friend void tag_invoke(std::execution::set_error_t, rvalue_receiver&& self, error const& e) noexcept(Noexcept) { + *self.called = &e; + } + }; + + template + struct lvalue_receiver + { + error const** called; + friend void tag_invoke(std::execution::set_error_t, lvalue_receiver& self, error const& e) noexcept(Noexcept) { + *self.called = &e; + } + }; + + template + struct const_receiver + { + error const** called; + friend void tag_invoke(std::execution::set_error_t, const_receiver const& self, error const& e) noexcept(Noexcept) { + *self.called = &e; + } + }; +} + +// ---------------------------------------------------------------------------- + +TEST(set_error, test_classes) +{ + static_assert(std::invocable, error>); + static_assert(std::invocable, error>); + static_assert(not std::invocable, no_error>); + static_assert(not std::invocable, no_error>); + static_assert(not std::invocable&, error>); + static_assert(not std::invocable&, error>); + static_assert(not std::invocable const&, error>); + static_assert(not std::invocable const&, error>); + static_assert(noexcept(tag_invoke(std::execution::set_error, std::declval>(), std::declval()))); + static_assert(not noexcept(tag_invoke(std::execution::set_error, std::declval>(), std::declval()))); + + static_assert(not std::invocable, error>); + static_assert(not std::invocable, error>); + static_assert(std::invocable&, error>); + static_assert(std::invocable&, error>); + static_assert(not std::invocable&, no_error>); + static_assert(not std::invocable&, no_error>); + static_assert(not std::invocable const&, error>); + static_assert(not std::invocable const&, error>); + static_assert(noexcept(tag_invoke(std::execution::set_error, std::declval&>(), std::declval()))); + static_assert(not noexcept(tag_invoke(std::execution::set_error, std::declval&>(), std::declval()))); + + static_assert(std::invocable, error>); + static_assert(std::invocable, error>); + static_assert(not std::invocable, no_error>); + static_assert(not std::invocable, no_error>); + static_assert(std::invocable&, error>); + static_assert(std::invocable&, error>); + static_assert(not std::invocable&, no_error>); + static_assert(not std::invocable&, no_error>); + static_assert(std::invocable const&, error>); + static_assert(std::invocable const&, error>); + static_assert(not std::invocable const&, no_error>); + static_assert(not std::invocable const&, no_error>); + static_assert(noexcept(tag_invoke(std::execution::set_error, std::declval>(), std::declval()))); + static_assert(not noexcept(tag_invoke(std::execution::set_error, std::declval>(), std::declval()))); + static_assert(noexcept(tag_invoke(std::execution::set_error, std::declval&>(), std::declval()))); + static_assert(not noexcept(tag_invoke(std::execution::set_error, std::declval&>(), std::declval()))); + static_assert(noexcept(tag_invoke(std::execution::set_error, std::declval const&>(), std::declval()))); + static_assert(not noexcept(tag_invoke(std::execution::set_error, std::declval const&>(), std::declval()))); +} + +TEST(set_error, rvalue_calls) +{ + static_assert(std::invocable, error>); + static_assert(not std::invocable, no_error>); + static_assert(not std::invocable, error>); + static_assert(not std::invocable&, error>); + static_assert(not std::invocable&, error>); + static_assert(not std::invocable const&, error>); + static_assert(not std::invocable const&, error>); + static_assert(noexcept(std::execution::set_error(std::declval>(), std::declval()))); + + error const* called{nullptr}; + error e{}; + + ASSERT_EQ(called, nullptr); + std::execution::set_error(rvalue_receiver{&called}, e); + EXPECT_EQ(called, &e); +} + +TEST(set_error, lvalue_calls) +{ + static_assert(not std::invocable, error>); + static_assert(not std::invocable, error>); + static_assert(std::invocable&, error>); + static_assert(not std::invocable&, no_error>); + static_assert(not std::invocable&, error>); + static_assert(not std::invocable const&, error>); + static_assert(not std::invocable const&, error>); + static_assert(noexcept(std::execution::set_error(std::declval&>(), std::declval()))); + + error const* called{nullptr}; + error e{}; + lvalue_receiver r{&called}; + + ASSERT_EQ(called, nullptr); + std::execution::set_error(r, e); + EXPECT_EQ(called, &e); +} + +TEST(set_error, const_calls) +{ + static_assert(std::invocable, error>); + static_assert(not std::invocable, no_error>); + static_assert(not std::invocable, error>); + static_assert(std::invocable&, error>); + static_assert(not std::invocable&, no_error>); + static_assert(not std::invocable&, error>); + static_assert(std::invocable const&, error>); + static_assert(not std::invocable&, no_error>); + static_assert(not std::invocable const&, error>); + static_assert(noexcept(std::execution::set_error(std::declval>(), std::declval()))); + static_assert(noexcept(std::execution::set_error(std::declval&>(), std::declval()))); + static_assert(noexcept(std::execution::set_error(std::declval const&>(), std::declval()))); + + { + error const* called{nullptr}; + error e{}; + + ASSERT_EQ(called, nullptr); + std::execution::set_error(const_receiver{&called}, e); + EXPECT_EQ(called, &e); + } + { + error const* called{nullptr}; + error e{}; + const_receiver r{&called}; + + ASSERT_EQ(called, nullptr); + std::execution::set_error(r, e); + EXPECT_EQ(called, &e); + } + { + error const* called{nullptr}; + error e{}; + const_receiver const r{&called}; + + ASSERT_EQ(called, nullptr); + std::execution::set_error(r, e); + EXPECT_EQ(called, &e); + } +} \ No newline at end of file From e2ccfe5bc3e727f5925cb72728326f9c051b94d1 Mon Sep 17 00:00:00 2001 From: Dietmar Kuehl Date: Sun, 6 Feb 2022 20:47:43 +0000 Subject: [PATCH 3/6] added set_value implementation --- CMakeLists.txt | 1 + README.md | 1 + include/execution.hpp | 1 + include/p2300/set_error.hpp | 3 + include/p2300/set_stopped.hpp | 1 - include/p2300/set_value.hpp | 58 +++++ test/set_value.cpp | 394 ++++++++++++++++++++++++++++++++++ test/test-config.hpp | 1 + 8 files changed, 459 insertions(+), 1 deletion(-) create mode 100644 include/p2300/set_value.hpp create mode 100644 test/set_value.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 522317f..cfac83c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,6 +62,7 @@ list(APPEND test_components test/operation_state.cpp test/set_error.cpp test/set_stopped.cpp + test/set_value.cpp test/start.cpp test/tag_invoke.cpp ) diff --git a/README.md b/README.md index 9c52dfd..23abe47 100644 --- a/README.md +++ b/README.md @@ -22,4 +22,5 @@ can be reported on the [P2300 issue tracker](https://github.com/brycelelbach/wg2 - `set_error(auto&& receiver, auto&& error) noexcept -> void` - `set_stopped(auto&& receiver) noexcept -> void` +- `set_value(auto&& receiver, auto&&... args) noexcept -> void` - `start(auto& state) noexcept -> void` diff --git a/include/execution.hpp b/include/execution.hpp index 33cec65..1a33d74 100644 --- a/include/execution.hpp +++ b/include/execution.hpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include diff --git a/include/p2300/set_error.hpp b/include/p2300/set_error.hpp index 7e4ad21..90a239d 100644 --- a/include/p2300/set_error.hpp +++ b/include/p2300/set_error.hpp @@ -26,6 +26,9 @@ #ifndef INCLUDED_INCLUDE_P2300_SET_ERROR #define INCLUDED_INCLUDE_P2300_SET_ERROR +#include +#include + // ---------------------------------------------------------------------------- namespace std { diff --git a/include/p2300/set_stopped.hpp b/include/p2300/set_stopped.hpp index 2eb1fed..93ceeca 100644 --- a/include/p2300/set_stopped.hpp +++ b/include/p2300/set_stopped.hpp @@ -27,7 +27,6 @@ #define INCLUDED_INCLUDE_P2300_SET_STOPPED #include -#include #include // ---------------------------------------------------------------------------- diff --git a/include/p2300/set_value.hpp b/include/p2300/set_value.hpp new file mode 100644 index 0000000..b662319 --- /dev/null +++ b/include/p2300/set_value.hpp @@ -0,0 +1,58 @@ +// include/p2300/set_value.hpp -*-C++-*- +// ---------------------------------------------------------------------------- +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, +// merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// ---------------------------------------------------------------------------- + +#ifndef INCLUDED_INCLUDE_P2300_SET_VALUE +#define INCLUDED_INCLUDE_P2300_SET_VALUE + +#include +#include + +// ---------------------------------------------------------------------------- + +namespace std { + namespace _Set_value { + class _Cpo { + public: + template + requires nothrow_tag_invocable<_Cpo, _Receiver, _Args...> + auto operator()(_Receiver&& __receiver, _Args&&... __args) const noexcept -> void + { + std::tag_invoke(*this, std::forward<_Receiver>(__receiver), std::forward<_Args>(__args)...); + } + }; + } + + namespace execution { + using set_value_t = _Set_value::_Cpo; + inline namespace _Cpos { + inline constexpr set_value_t set_value{}; + } + } +} + + +// ---------------------------------------------------------------------------- + +#endif diff --git a/test/set_value.cpp b/test/set_value.cpp new file mode 100644 index 0000000..6b1fd02 --- /dev/null +++ b/test/set_value.cpp @@ -0,0 +1,394 @@ +// test/set_value.cpp -*-C++-*- +// ---------------------------------------------------------------------------- +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, +// merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// ---------------------------------------------------------------------------- + +#include "test-config.hpp" +#include P2300_execution +#include P2300_tuple +#include P2300_type_traits +#include + +// ---------------------------------------------------------------------------- + +namespace +{ + template struct arg {}; + struct no_arg {}; + + template + struct rvalue_receiver + { + using Args = std::tuple>...>; + static Args args; + Args** called; + friend void tag_invoke(std::execution::set_value_t, rvalue_receiver&& self, A... a) noexcept(Noexcept) { + self.args = std::make_tuple(&a...); + *self.called = &self.args; + } + }; + template + typename rvalue_receiver::Args rvalue_receiver::args{}; + + template + struct lvalue_receiver + { + using Args = std::tuple>...>; + static Args args; + Args** called; + friend void tag_invoke(std::execution::set_value_t, lvalue_receiver& self, A... a) noexcept(Noexcept) { + self.args = std::make_tuple(&a...); + *self.called = &self.args; + } + }; + template + typename lvalue_receiver::Args lvalue_receiver::args{}; + + template + struct const_receiver + { + using Args = std::tuple>...>; + static Args args; + Args** called; + friend void tag_invoke(std::execution::set_value_t, const_receiver const& self, A... a) noexcept(Noexcept) { + self.args = std::make_tuple(&a...); + *self.called = &self.args; + } + }; + template + typename const_receiver::Args const_receiver::args{}; +} + +// ---------------------------------------------------------------------------- + +TEST(set_value, test_classes) +{ + // rvalue_receiver + static_assert(std::invocable>); + static_assert(std::invocable>); + static_assert(std::invocable>, arg<0>>); + static_assert(std::invocable>, arg<0>>); + static_assert(std::invocable, arg<1>, arg<2>>, arg<0>, arg<1>, arg<2>>); + static_assert(std::invocable, arg<1>, arg<2>>, arg<0>, arg<1>, arg<2>>); + static_assert(not std::invocable>, no_arg>); + static_assert(not std::invocable>, no_arg>); + + static_assert(not std::invocable&>); + static_assert(not std::invocable&>); + + static_assert(not std::invocable const&>); + static_assert(not std::invocable const&>); + + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval>>(), std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>>(), std::declval>(), std::declval>(), std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval>>(), std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>>(), std::declval>(), std::declval>(), std::declval>()))); + + // lvalue_receiver + static_assert(not std::invocable>); + static_assert(not std::invocable>); + + static_assert(std::invocable&>); + static_assert(std::invocable&>); + static_assert(std::invocable>&, arg<0>>); + static_assert(std::invocable>&, arg<0>>); + static_assert(std::invocable, arg<1>, arg<2>>&, arg<0>, arg<1>, arg<2>>); + static_assert(std::invocable, arg<1>, arg<2>>&, arg<0>, arg<1>, arg<2>>); + static_assert(not std::invocable>&, no_arg>); + static_assert(not std::invocable>&, no_arg>); + + static_assert(not std::invocable const&>); + static_assert(not std::invocable const&>); + + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval&>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval>&>(), std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>&>(), std::declval>(), std::declval>(), std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval&>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval>&>(), std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>&>(), std::declval>(), std::declval>(), std::declval>()))); + + // const_receiver + static_assert(std::invocable>); + static_assert(std::invocable>); + static_assert(std::invocable>, arg<0>>); + static_assert(std::invocable>, arg<0>>); + static_assert(std::invocable, arg<1>, arg<2>>, arg<0>, arg<1>, arg<2>>); + static_assert(std::invocable, arg<1>, arg<2>>, arg<0>, arg<1>, arg<2>>); + static_assert(not std::invocable>, no_arg>); + static_assert(not std::invocable>, no_arg>); + + static_assert(std::invocable&>); + static_assert(std::invocable&>); + static_assert(std::invocable>&, arg<0>>); + static_assert(std::invocable>&, arg<0>>); + static_assert(std::invocable, arg<1>, arg<2>>&, arg<0>, arg<1>, arg<2>>); + static_assert(std::invocable, arg<1>, arg<2>>&, arg<0>, arg<1>, arg<2>>); + static_assert(not std::invocable>&, no_arg>); + static_assert(not std::invocable>&, no_arg>); + + static_assert(std::invocable const&>); + static_assert(std::invocable const&>); + static_assert(std::invocable> const&, arg<0>>); + static_assert(std::invocable> const&, arg<0>>); + static_assert(std::invocable, arg<1>, arg<2>> const&, arg<0>, arg<1>, arg<2>>); + static_assert(std::invocable, arg<1>, arg<2>> const&, arg<0>, arg<1>, arg<2>>); + static_assert(not std::invocable> const&, no_arg>); + static_assert(not std::invocable> const&, no_arg>); + + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval>>(), std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>>(), std::declval>(), std::declval>(), std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval>>(), std::declval>()))); + + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval&>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval>&>(), std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>&>(), std::declval>(), std::declval>(), std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval&>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval>&>(), std::declval>()))); + + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval const&>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval> const&>(), std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>> const&>(), std::declval>(), std::declval>(), std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval const&>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval> const&>(), std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>> const&>(), std::declval>(), std::declval>(), std::declval>()))); +} + +TEST(set_value, rvalue_calls) +{ + static_assert(std::invocable>); + static_assert(std::invocable>, arg<0>>); + static_assert(not std::invocable>, no_arg>); + static_assert(std::invocable, arg<1>, arg<2>>, arg<0>, arg<1>, arg<2>>); + static_assert(not std::invocable>); + static_assert(not std::invocable&>); + static_assert(not std::invocable&>); + static_assert(not std::invocable const&>); + static_assert(not std::invocable const&>); + static_assert(noexcept(std::execution::set_value(std::declval>()))); + + { + std::tuple<>* called{nullptr}; + ASSERT_EQ(called, nullptr); + std::execution::set_value(rvalue_receiver{&called}); + EXPECT_NE(called, nullptr); + } + { + std::tuple*>* called{nullptr}; + arg<0> arg0{}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(rvalue_receiver&>{&called}, arg0); + EXPECT_NE(called, nullptr); + EXPECT_EQ(*called, std::make_tuple(&arg0)); + } + { + std::tuple*, arg<1>*, arg<2>*>* called{nullptr}; + arg<0> arg0{}; + arg<1> arg1{}; + arg<2> arg2{}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(rvalue_receiver&, arg<1>&, arg<2>&>{&called}, arg0, arg1, arg2); + EXPECT_NE(called, nullptr); + EXPECT_EQ(*called, std::make_tuple(&arg0, &arg1, &arg2)); + } +} + +TEST(set_value, lvalue_calls) +{ + static_assert(not std::invocable>); + static_assert(not std::invocable>); + + static_assert(std::invocable&>); + static_assert(std::invocable>&, arg<0>>); + static_assert(not std::invocable>&, no_arg>); + static_assert(std::invocable, arg<1>, arg<2>>&, arg<0>, arg<1>, arg<2>>); + static_assert(not std::invocable&>); + static_assert(not std::invocable>&, arg<0>>); + static_assert(not std::invocable,arg<1>, arg<2>>&, arg<0>,arg<1>, arg<2>>); + + static_assert(not std::invocable const&>); + static_assert(not std::invocable const&>); + + static_assert(noexcept(std::execution::set_value(std::declval&>()))); + static_assert(noexcept(std::execution::set_value(std::declval&>&>(), std::declval&>()))); + static_assert(noexcept(std::execution::set_value(std::declval&, arg<1>&, arg<2>&>&>(), std::declval&>(), std::declval&>(), std::declval&>()))); + + { + std::tuple<>* called{nullptr}; + lvalue_receiver receiver{&called}; + ASSERT_EQ(called, nullptr); + std::execution::set_value(receiver); + EXPECT_NE(called, nullptr); + } + { + std::tuple*>* called{nullptr}; + lvalue_receiver&> receiver{&called}; + arg<0> arg0{}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(receiver, arg0); + EXPECT_NE(called, nullptr); + EXPECT_EQ(*called, std::make_tuple(&arg0)); + } + { + std::tuple*, arg<1>*, arg<2>*>* called{nullptr}; + lvalue_receiver&, arg<1>&, arg<2>&> receiver{&called}; + arg<0> arg0{}; + arg<1> arg1{}; + arg<2> arg2{}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(receiver, arg0, arg1, arg2); + EXPECT_NE(called, nullptr); + EXPECT_EQ(*called, std::make_tuple(&arg0, &arg1, &arg2)); + } +} + +// ---------------------------------------------------------------------------- + +TEST(set_value, const_calls) +{ + static_assert(std::invocable>); + static_assert(std::invocable>, arg<0>>); + static_assert(std::invocable, arg<1>, arg<2>>, arg<0>, arg<1>, arg<2>>); + static_assert(not std::invocable>); + static_assert(not std::invocable>, arg<0>>); + static_assert(not std::invocable, arg<1>, arg<2>>, arg<0>, arg<1>, arg<2>>); + + static_assert(std::invocable&>); + static_assert(std::invocable>&, arg<0>>); + static_assert(std::invocable, arg<1>, arg<2>>&, arg<0>, arg<1>, arg<2>>); + static_assert(not std::invocable&>); + static_assert(not std::invocable>&, arg<0>>); + static_assert(not std::invocable, arg<1>, arg<2>>&, arg<0>, arg<1>, arg<2>>); + + static_assert(std::invocable const&>); + static_assert(std::invocable> const&, arg<0>>); + static_assert(std::invocable, arg<1>, arg<2>> const&, arg<0>, arg<1>, arg<2>>); + static_assert(not std::invocable const&>); + static_assert(not std::invocable> const&, arg<0>>); + static_assert(not std::invocable, arg<1>, arg<2>> const&, arg<0>, arg<1>, arg<2>>); + + static_assert(noexcept(std::execution::set_value(std::declval>()))); + static_assert(noexcept(std::execution::set_value(std::declval>>(), std::declval>()))); + static_assert(noexcept(std::execution::set_value(std::declval, arg<1>, arg<2>>>(), std::declval>(), std::declval>(), std::declval>()))); + + static_assert(noexcept(std::execution::set_value(std::declval&>()))); + static_assert(noexcept(std::execution::set_value(std::declval>&>(), std::declval>()))); + static_assert(noexcept(std::execution::set_value(std::declval, arg<1>, arg<2>>&>(), std::declval>(), std::declval>(), std::declval>()))); + + { + std::tuple<>* called{nullptr}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(const_receiver{&called}); + EXPECT_NE(called, nullptr); + } + { + std::tuple*>* called{nullptr}; + arg<0> arg0{}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(const_receiver&>{&called}, arg0); + EXPECT_NE(called, nullptr); + EXPECT_EQ(*called, std::make_tuple(&arg0)); + } + { + std::tuple*, arg<1>*, arg<2>*>* called{nullptr}; + arg<0> arg0{}; + arg<1> arg1{}; + arg<2> arg2{}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(const_receiver&, arg<1>&, arg<2>&>{&called}, arg0, arg1, arg2); + EXPECT_NE(called, nullptr); + EXPECT_EQ(*called, std::make_tuple(&arg0, &arg1, &arg2)); + } + + { + std::tuple<>* called{nullptr}; + const_receiver receiver{&called}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(receiver); + EXPECT_NE(called, nullptr); + } + { + std::tuple*>* called{nullptr}; + const_receiver&> receiver{&called}; + arg<0> arg0{}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(receiver, arg0); + EXPECT_NE(called, nullptr); + EXPECT_EQ(*called, std::make_tuple(&arg0)); + } + { + std::tuple*, arg<1>*, arg<2>*>* called{nullptr}; + const_receiver&, arg<1>&, arg<2>&> receiver{&called}; + arg<0> arg0{}; + arg<1> arg1{}; + arg<2> arg2{}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(receiver, arg0, arg1, arg2); + EXPECT_NE(called, nullptr); + EXPECT_EQ(*called, std::make_tuple(&arg0, &arg1, &arg2)); + } + + { + std::tuple<>* called{nullptr}; + const_receiver const receiver{&called}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(receiver); + EXPECT_NE(called, nullptr); + } + { + std::tuple*>* called{nullptr}; + const_receiver&> const receiver{&called}; + arg<0> arg0{}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(receiver, arg0); + EXPECT_NE(called, nullptr); + EXPECT_EQ(*called, std::make_tuple(&arg0)); + } + { + std::tuple*, arg<1>*, arg<2>*>* called{nullptr}; + const_receiver&, arg<1>&, arg<2>&> const receiver{&called}; + arg<0> arg0{}; + arg<1> arg1{}; + arg<2> arg2{}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(receiver, arg0, arg1, arg2); + EXPECT_NE(called, nullptr); + EXPECT_EQ(*called, std::make_tuple(&arg0, &arg1, &arg2)); + } +} \ No newline at end of file diff --git a/test/test-config.hpp b/test/test-config.hpp index 6e52d57..607ebfa 100644 --- a/test/test-config.hpp +++ b/test/test-config.hpp @@ -36,6 +36,7 @@ #define P2300_execution #define P2300_functional +#define P2300_tuple #define P2300_type_traits // ---------------------------------------------------------------------------- From ab368c29cc68645734cc5850dad86c8674695ef3 Mon Sep 17 00:00:00 2001 From: Dietmar Kuehl Date: Sun, 6 Feb 2022 20:53:18 +0000 Subject: [PATCH 4/6] fixed year on copyright --- include/execution.hpp | 2 +- include/functional.hpp | 2 +- include/p2300/callable.hpp | 2 +- include/p2300/movable_value.hpp | 2 +- include/p2300/non_associated.hpp | 2 +- include/p2300/tag_invoke.hpp | 2 +- std-headers/functional | 2 +- test/call_result_t.cpp | 4 ++-- test/callable.cpp | 4 ++-- test/movable_value.cpp | 2 +- test/non_associated.cpp | 2 +- test/nothrow_callable.cpp | 4 ++-- test/tag_invoke.cpp | 2 +- test/test-config.hpp | 2 +- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/execution.hpp b/include/execution.hpp index 1a33d74..e8893f5 100644 --- a/include/execution.hpp +++ b/include/execution.hpp @@ -1,6 +1,6 @@ // include/execution.hpp -*-C++-*- // ---------------------------------------------------------------------------- -// Copyright (C) 2021 Dietmar Kuehl http://www.dietmar-kuehl.de +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/include/functional.hpp b/include/functional.hpp index 77f865d..6de2d0d 100644 --- a/include/functional.hpp +++ b/include/functional.hpp @@ -1,6 +1,6 @@ // include/functional.hpp -*-C++-*- // ---------------------------------------------------------------------------- -// Copyright (C) 2021 Dietmar Kuehl http://www.dietmar-kuehl.de +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/include/p2300/callable.hpp b/include/p2300/callable.hpp index a66fa88..ec91564 100644 --- a/include/p2300/callable.hpp +++ b/include/p2300/callable.hpp @@ -1,6 +1,6 @@ // include/p2300/callable.hpp -*-C++-*- // ---------------------------------------------------------------------------- -// Copyright (C) 2021 Dietmar Kuehl http://www.dietmar-kuehl.de +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/include/p2300/movable_value.hpp b/include/p2300/movable_value.hpp index 328ad32..ab48be1 100644 --- a/include/p2300/movable_value.hpp +++ b/include/p2300/movable_value.hpp @@ -1,6 +1,6 @@ // include/p2300/moveable.hpp -*-C++-*- // ---------------------------------------------------------------------------- -// Copyright (C) 2021 Dietmar Kuehl http://www.dietmar-kuehl.de +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/include/p2300/non_associated.hpp b/include/p2300/non_associated.hpp index 446e89f..184867d 100644 --- a/include/p2300/non_associated.hpp +++ b/include/p2300/non_associated.hpp @@ -1,6 +1,6 @@ // include/p2300/non_associated.hpp -*-C++-*- // ---------------------------------------------------------------------------- -// Copyright (C) 2021 Dietmar Kuehl http://www.dietmar-kuehl.de +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/include/p2300/tag_invoke.hpp b/include/p2300/tag_invoke.hpp index e9d9ee1..8c5099d 100644 --- a/include/p2300/tag_invoke.hpp +++ b/include/p2300/tag_invoke.hpp @@ -1,6 +1,6 @@ // include/p2300/tag_invoke.hpp -*-C++-*- // ---------------------------------------------------------------------------- -// Copyright (C) 2021 Dietmar Kuehl http://www.dietmar-kuehl.de +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/std-headers/functional b/std-headers/functional index c1be113..d8fb77a 100644 --- a/std-headers/functional +++ b/std-headers/functional @@ -1,6 +1,6 @@ // std-headers/functional -*-C++-*- // ---------------------------------------------------------------------------- -// Copyright (C) 2021 Dietmar Kuehl http://www.dietmar-kuehl.de +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/test/call_result_t.cpp b/test/call_result_t.cpp index 435c7e3..0415517 100644 --- a/test/call_result_t.cpp +++ b/test/call_result_t.cpp @@ -1,6 +1,6 @@ // test/call_result_t.cpp -*-C++-*- // ---------------------------------------------------------------------------- -// Copyright (C) 2021 Dietmar Kuehl http://www.dietmar-kuehl.de +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -56,4 +56,4 @@ TEST(call_result_t, function_objects) EXPECT_TRUE((P2300_std::is_same_v, void>)); EXPECT_TRUE((P2300_std::is_same_v, bool>)); EXPECT_TRUE((P2300_std::is_same_v, double>)); -} \ No newline at end of file +} diff --git a/test/callable.cpp b/test/callable.cpp index 1984e1e..8c74d0b 100644 --- a/test/callable.cpp +++ b/test/callable.cpp @@ -1,6 +1,6 @@ // test/callable.cpp -*-C++-*- // ---------------------------------------------------------------------------- -// Copyright (C) 2021 Dietmar Kuehl http://www.dietmar-kuehl.de +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -60,4 +60,4 @@ TEST(callable, function_objects) EXPECT_TRUE((P2300_callable)); EXPECT_TRUE((P2300_callable)); EXPECT_TRUE((P2300_callable)); -} \ No newline at end of file +} diff --git a/test/movable_value.cpp b/test/movable_value.cpp index f66e46d..5810e6e 100644 --- a/test/movable_value.cpp +++ b/test/movable_value.cpp @@ -1,6 +1,6 @@ // test/movable_value.cpp -*-C++-*- // ---------------------------------------------------------------------------- -// Copyright (C) 2021 Dietmar Kuehl http://www.dietmar-kuehl.de +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/test/non_associated.cpp b/test/non_associated.cpp index 409f8d8..bb2519b 100644 --- a/test/non_associated.cpp +++ b/test/non_associated.cpp @@ -1,6 +1,6 @@ // test/non_associated.cpp -*-C++-*- // ---------------------------------------------------------------------------- -// Copyright (C) 2021 Dietmar Kuehl http://www.dietmar-kuehl.de +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/test/nothrow_callable.cpp b/test/nothrow_callable.cpp index 14e3fd8..4cfe5b6 100644 --- a/test/nothrow_callable.cpp +++ b/test/nothrow_callable.cpp @@ -1,6 +1,6 @@ // test/nothrow_callable.cpp -*-C++-*- // ---------------------------------------------------------------------------- -// Copyright (C) 2021 Dietmar Kuehl http://www.dietmar-kuehl.de +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -72,4 +72,4 @@ TEST(nothrow_callable, function_objects) EXPECT_FALSE((P2300_nothrow_callable)); EXPECT_TRUE((P2300_nothrow_callable)); EXPECT_FALSE((P2300_nothrow_callable)); -} \ No newline at end of file +} diff --git a/test/tag_invoke.cpp b/test/tag_invoke.cpp index 859c820..ac0cef7 100644 --- a/test/tag_invoke.cpp +++ b/test/tag_invoke.cpp @@ -1,6 +1,6 @@ // test/tag_invoke.cpp -*-C++-*- // ---------------------------------------------------------------------------- -// Copyright (C) 2021 Dietmar Kuehl http://www.dietmar-kuehl.de +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/test/test-config.hpp b/test/test-config.hpp index 607ebfa..522284c 100644 --- a/test/test-config.hpp +++ b/test/test-config.hpp @@ -1,6 +1,6 @@ // test/test-config.hpp -*-C++-*- // ---------------------------------------------------------------------------- -// Copyright (C) 2021 Dietmar Kuehl http://www.dietmar-kuehl.de +// Copyright (C) 2022 Dietmar Kuehl http://www.dietmar-kuehl.de // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation From 522e8d447701158ad317c68c66cdad6136eb4611 Mon Sep 17 00:00:00 2001 From: Dietmar Kuehl Date: Sun, 6 Feb 2022 21:11:14 +0000 Subject: [PATCH 5/6] added some clarification to the README.md --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 23abe47..ed0d087 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,10 @@ can be reported on the [P2300 issue tracker](https://github.com/brycelelbach/wg2 ## Concept Overview +This section is intended to yield an overview of the used concepts. +The primary purpose is to serve as a quick reference of what needs +to be implemented rather than necessarily capturing all details. + - `operation_state` template @@ -18,7 +22,14 @@ can be reported on the [P2300 issue tracker](https://github.com/brycelelbach/wg2 && requires(S& s) { { execution::start(s) } noexcept; } ; -## Customization Point Overview +## Customization Point Object Overview + +This section is intended to yield and overview of the user customization +point objects. The notation resembles how the customization points +can be called. It doesn't represent their respective implementation. +This section is intend as quick reference when implementing the +corresponding customization rather than necessarily capturing all +details. - `set_error(auto&& receiver, auto&& error) noexcept -> void` - `set_stopped(auto&& receiver) noexcept -> void` From 37d75d75bffbaef42b5d5121fd3a03680fde13ff Mon Sep 17 00:00:00 2001 From: Dietmar Kuehl Date: Mon, 7 Feb 2022 23:52:34 +0000 Subject: [PATCH 6/6] addressed review comments --- test/set_error.cpp | 103 +++++++++++++++++++++++++++++---- test/set_value.cpp | 140 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 232 insertions(+), 11 deletions(-) diff --git a/test/set_error.cpp b/test/set_error.cpp index fa8986c..60837bd 100644 --- a/test/set_error.cpp +++ b/test/set_error.cpp @@ -34,6 +34,7 @@ namespace { struct error {}; struct no_error {}; + struct conv { operator error() const noexcept { return {}; } }; template struct rvalue_receiver @@ -67,65 +68,101 @@ namespace TEST(set_error, test_classes) { + static_assert(std::is_convertible_v); static_assert(std::invocable, error>); static_assert(std::invocable, error>); + static_assert(std::invocable, conv>); + static_assert(std::invocable, conv>); static_assert(not std::invocable, no_error>); static_assert(not std::invocable, no_error>); static_assert(not std::invocable&, error>); static_assert(not std::invocable&, error>); static_assert(not std::invocable const&, error>); static_assert(not std::invocable const&, error>); + static_assert(noexcept(tag_invoke(std::execution::set_error, std::declval>(), std::declval()))); static_assert(not noexcept(tag_invoke(std::execution::set_error, std::declval>(), std::declval()))); + static_assert(noexcept(tag_invoke(std::execution::set_error, std::declval>(), std::declval()))); + static_assert(not noexcept(tag_invoke(std::execution::set_error, std::declval>(), std::declval()))); static_assert(not std::invocable, error>); static_assert(not std::invocable, error>); static_assert(std::invocable&, error>); static_assert(std::invocable&, error>); + static_assert(std::invocable&, conv>); + static_assert(std::invocable&, conv>); static_assert(not std::invocable&, no_error>); static_assert(not std::invocable&, no_error>); static_assert(not std::invocable const&, error>); static_assert(not std::invocable const&, error>); + static_assert(noexcept(tag_invoke(std::execution::set_error, std::declval&>(), std::declval()))); static_assert(not noexcept(tag_invoke(std::execution::set_error, std::declval&>(), std::declval()))); + static_assert(noexcept(tag_invoke(std::execution::set_error, std::declval&>(), std::declval()))); + static_assert(not noexcept(tag_invoke(std::execution::set_error, std::declval&>(), std::declval()))); static_assert(std::invocable, error>); static_assert(std::invocable, error>); + static_assert(std::invocable, conv>); + static_assert(std::invocable, conv>); static_assert(not std::invocable, no_error>); static_assert(not std::invocable, no_error>); static_assert(std::invocable&, error>); static_assert(std::invocable&, error>); + static_assert(std::invocable&, conv>); + static_assert(std::invocable&, conv>); static_assert(not std::invocable&, no_error>); static_assert(not std::invocable&, no_error>); static_assert(std::invocable const&, error>); static_assert(std::invocable const&, error>); + static_assert(std::invocable const&, conv>); + static_assert(std::invocable const&, conv>); static_assert(not std::invocable const&, no_error>); static_assert(not std::invocable const&, no_error>); + static_assert(noexcept(tag_invoke(std::execution::set_error, std::declval>(), std::declval()))); static_assert(not noexcept(tag_invoke(std::execution::set_error, std::declval>(), std::declval()))); + static_assert(noexcept(tag_invoke(std::execution::set_error, std::declval>(), std::declval()))); + static_assert(not noexcept(tag_invoke(std::execution::set_error, std::declval>(), std::declval()))); static_assert(noexcept(tag_invoke(std::execution::set_error, std::declval&>(), std::declval()))); static_assert(not noexcept(tag_invoke(std::execution::set_error, std::declval&>(), std::declval()))); + static_assert(noexcept(tag_invoke(std::execution::set_error, std::declval&>(), std::declval()))); + static_assert(not noexcept(tag_invoke(std::execution::set_error, std::declval&>(), std::declval()))); static_assert(noexcept(tag_invoke(std::execution::set_error, std::declval const&>(), std::declval()))); static_assert(not noexcept(tag_invoke(std::execution::set_error, std::declval const&>(), std::declval()))); + static_assert(noexcept(tag_invoke(std::execution::set_error, std::declval const&>(), std::declval()))); + static_assert(not noexcept(tag_invoke(std::execution::set_error, std::declval const&>(), std::declval()))); } TEST(set_error, rvalue_calls) { static_assert(std::invocable, error>); + static_assert(std::invocable, conv>); static_assert(not std::invocable, no_error>); static_assert(not std::invocable, error>); + static_assert(not std::invocable, conv>); static_assert(not std::invocable&, error>); static_assert(not std::invocable&, error>); static_assert(not std::invocable const&, error>); static_assert(not std::invocable const&, error>); static_assert(noexcept(std::execution::set_error(std::declval>(), std::declval()))); + static_assert(noexcept(std::execution::set_error(std::declval>(), std::declval()))); + + { + error const* called{nullptr}; + error e{}; - error const* called{nullptr}; - error e{}; + ASSERT_EQ(called, nullptr); + std::execution::set_error(rvalue_receiver{&called}, e); + EXPECT_EQ(called, &e); + } + { + error const* called{nullptr}; - ASSERT_EQ(called, nullptr); - std::execution::set_error(rvalue_receiver{&called}, e); - EXPECT_EQ(called, &e); + ASSERT_EQ(called, nullptr); + std::execution::set_error(rvalue_receiver{&called}, conv{}); + EXPECT_NE(called, nullptr); + } } TEST(set_error, lvalue_calls) @@ -133,35 +170,56 @@ TEST(set_error, lvalue_calls) static_assert(not std::invocable, error>); static_assert(not std::invocable, error>); static_assert(std::invocable&, error>); + static_assert(std::invocable&, conv>); static_assert(not std::invocable&, no_error>); static_assert(not std::invocable&, error>); static_assert(not std::invocable const&, error>); static_assert(not std::invocable const&, error>); static_assert(noexcept(std::execution::set_error(std::declval&>(), std::declval()))); + static_assert(noexcept(std::execution::set_error(std::declval&>(), std::declval()))); + + { + error const* called{nullptr}; + error e{}; + lvalue_receiver r{&called}; - error const* called{nullptr}; - error e{}; - lvalue_receiver r{&called}; + ASSERT_EQ(called, nullptr); + std::execution::set_error(r, e); + EXPECT_EQ(called, &e); + } + { + error const* called{nullptr}; + lvalue_receiver r{&called}; - ASSERT_EQ(called, nullptr); - std::execution::set_error(r, e); - EXPECT_EQ(called, &e); + ASSERT_EQ(called, nullptr); + std::execution::set_error(r, conv{}); + EXPECT_NE(called, nullptr); + } } TEST(set_error, const_calls) { static_assert(std::invocable, error>); + static_assert(std::invocable, conv>); static_assert(not std::invocable, no_error>); static_assert(not std::invocable, error>); + static_assert(not std::invocable, conv>); static_assert(std::invocable&, error>); + static_assert(std::invocable&, conv>); static_assert(not std::invocable&, no_error>); static_assert(not std::invocable&, error>); + static_assert(not std::invocable&, conv>); static_assert(std::invocable const&, error>); + static_assert(std::invocable const&, conv>); static_assert(not std::invocable&, no_error>); static_assert(not std::invocable const&, error>); + static_assert(not std::invocable const&, conv>); static_assert(noexcept(std::execution::set_error(std::declval>(), std::declval()))); + static_assert(noexcept(std::execution::set_error(std::declval>(), std::declval()))); static_assert(noexcept(std::execution::set_error(std::declval&>(), std::declval()))); + static_assert(noexcept(std::execution::set_error(std::declval&>(), std::declval()))); static_assert(noexcept(std::execution::set_error(std::declval const&>(), std::declval()))); + static_assert(noexcept(std::execution::set_error(std::declval const&>(), std::declval()))); { error const* called{nullptr}; @@ -171,6 +229,13 @@ TEST(set_error, const_calls) std::execution::set_error(const_receiver{&called}, e); EXPECT_EQ(called, &e); } + { + error const* called{nullptr}; + + ASSERT_EQ(called, nullptr); + std::execution::set_error(const_receiver{&called}, conv{}); + EXPECT_NE(called, nullptr); + } { error const* called{nullptr}; error e{}; @@ -180,6 +245,14 @@ TEST(set_error, const_calls) std::execution::set_error(r, e); EXPECT_EQ(called, &e); } + { + error const* called{nullptr}; + const_receiver r{&called}; + + ASSERT_EQ(called, nullptr); + std::execution::set_error(r, conv{}); + EXPECT_NE(called, nullptr); + } { error const* called{nullptr}; error e{}; @@ -189,4 +262,12 @@ TEST(set_error, const_calls) std::execution::set_error(r, e); EXPECT_EQ(called, &e); } + { + error const* called{nullptr}; + const_receiver const r{&called}; + + ASSERT_EQ(called, nullptr); + std::execution::set_error(r, conv{}); + EXPECT_NE(called, nullptr); + } } \ No newline at end of file diff --git a/test/set_value.cpp b/test/set_value.cpp index 6b1fd02..0a5ed20 100644 --- a/test/set_value.cpp +++ b/test/set_value.cpp @@ -35,6 +35,7 @@ namespace { template struct arg {}; struct no_arg {}; + template struct conv { operator arg() const noexcept { return {}; } }; template struct rvalue_receiver @@ -83,13 +84,18 @@ namespace TEST(set_value, test_classes) { + static_assert(std::is_convertible_v, arg<1>>); // rvalue_receiver static_assert(std::invocable>); static_assert(std::invocable>); static_assert(std::invocable>, arg<0>>); static_assert(std::invocable>, arg<0>>); + static_assert(std::invocable>, conv<0>>); + static_assert(std::invocable>, conv<0>>); static_assert(std::invocable, arg<1>, arg<2>>, arg<0>, arg<1>, arg<2>>); static_assert(std::invocable, arg<1>, arg<2>>, arg<0>, arg<1>, arg<2>>); + static_assert(std::invocable, arg<1>, arg<2>>, conv<0>, conv<1>, conv<2>>); + static_assert(std::invocable, arg<1>, arg<2>>, conv<0>, conv<1>, conv<2>>); static_assert(not std::invocable>, no_arg>); static_assert(not std::invocable>, no_arg>); @@ -101,10 +107,14 @@ TEST(set_value, test_classes) static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval>()))); static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval>>(), std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval>>(), std::declval>()))); static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>>(), std::declval>(), std::declval>(), std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>>(), std::declval>(), std::declval>(), std::declval>()))); static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval>()))); static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval>>(), std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval>>(), std::declval>()))); static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>>(), std::declval>(), std::declval>(), std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>>(), std::declval>(), std::declval>(), std::declval>()))); // lvalue_receiver static_assert(not std::invocable>); @@ -114,8 +124,12 @@ TEST(set_value, test_classes) static_assert(std::invocable&>); static_assert(std::invocable>&, arg<0>>); static_assert(std::invocable>&, arg<0>>); + static_assert(std::invocable>&, conv<0>>); + static_assert(std::invocable>&, conv<0>>); static_assert(std::invocable, arg<1>, arg<2>>&, arg<0>, arg<1>, arg<2>>); static_assert(std::invocable, arg<1>, arg<2>>&, arg<0>, arg<1>, arg<2>>); + static_assert(std::invocable, arg<1>, arg<2>>&, conv<0>, conv<1>, conv<2>>); + static_assert(std::invocable, arg<1>, arg<2>>&, conv<0>, conv<1>, conv<2>>); static_assert(not std::invocable>&, no_arg>); static_assert(not std::invocable>&, no_arg>); @@ -124,18 +138,26 @@ TEST(set_value, test_classes) static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval&>()))); static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval>&>(), std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval>&>(), std::declval>()))); static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>&>(), std::declval>(), std::declval>(), std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>&>(), std::declval>(), std::declval>(), std::declval>()))); static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval&>()))); static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval>&>(), std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval>&>(), std::declval>()))); static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>&>(), std::declval>(), std::declval>(), std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>&>(), std::declval>(), std::declval>(), std::declval>()))); // const_receiver static_assert(std::invocable>); static_assert(std::invocable>); static_assert(std::invocable>, arg<0>>); static_assert(std::invocable>, arg<0>>); + static_assert(std::invocable>, conv<0>>); + static_assert(std::invocable>, conv<0>>); static_assert(std::invocable, arg<1>, arg<2>>, arg<0>, arg<1>, arg<2>>); static_assert(std::invocable, arg<1>, arg<2>>, arg<0>, arg<1>, arg<2>>); + static_assert(std::invocable, arg<1>, arg<2>>, conv<0>, conv<1>, conv<2>>); + static_assert(std::invocable, arg<1>, arg<2>>, conv<0>, conv<1>, conv<2>>); static_assert(not std::invocable>, no_arg>); static_assert(not std::invocable>, no_arg>); @@ -143,8 +165,12 @@ TEST(set_value, test_classes) static_assert(std::invocable&>); static_assert(std::invocable>&, arg<0>>); static_assert(std::invocable>&, arg<0>>); + static_assert(std::invocable>&, conv<0>>); + static_assert(std::invocable>&, conv<0>>); static_assert(std::invocable, arg<1>, arg<2>>&, arg<0>, arg<1>, arg<2>>); static_assert(std::invocable, arg<1>, arg<2>>&, arg<0>, arg<1>, arg<2>>); + static_assert(std::invocable, arg<1>, arg<2>>&, conv<0>, conv<1>, conv<2>>); + static_assert(std::invocable, arg<1>, arg<2>>&, conv<0>, conv<1>, conv<2>>); static_assert(not std::invocable>&, no_arg>); static_assert(not std::invocable>&, no_arg>); @@ -152,37 +178,53 @@ TEST(set_value, test_classes) static_assert(std::invocable const&>); static_assert(std::invocable> const&, arg<0>>); static_assert(std::invocable> const&, arg<0>>); + static_assert(std::invocable> const&, conv<0>>); + static_assert(std::invocable> const&, conv<0>>); static_assert(std::invocable, arg<1>, arg<2>> const&, arg<0>, arg<1>, arg<2>>); static_assert(std::invocable, arg<1>, arg<2>> const&, arg<0>, arg<1>, arg<2>>); + static_assert(std::invocable, arg<1>, arg<2>> const&, conv<0>, conv<1>, conv<2>>); + static_assert(std::invocable, arg<1>, arg<2>> const&, conv<0>, conv<1>, conv<2>>); static_assert(not std::invocable> const&, no_arg>); static_assert(not std::invocable> const&, no_arg>); static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval>()))); static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval>>(), std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval>>(), std::declval>()))); static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>>(), std::declval>(), std::declval>(), std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>>(), std::declval>(), std::declval>(), std::declval>()))); static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval>()))); static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval>>(), std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval>>(), std::declval>()))); static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval&>()))); static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval>&>(), std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval>&>(), std::declval>()))); static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>&>(), std::declval>(), std::declval>(), std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>>&>(), std::declval>(), std::declval>(), std::declval>()))); static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval&>()))); static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval>&>(), std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval>&>(), std::declval>()))); static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval const&>()))); static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval> const&>(), std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval> const&>(), std::declval>()))); static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>> const&>(), std::declval>(), std::declval>(), std::declval>()))); + static_assert(noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>> const&>(), std::declval>(), std::declval>(), std::declval>()))); static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval const&>()))); static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval> const&>(), std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval> const&>(), std::declval>()))); static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>> const&>(), std::declval>(), std::declval>(), std::declval>()))); + static_assert(not noexcept(tag_invoke(std::execution::set_value, std::declval, arg<1>, arg<2>> const&>(), std::declval>(), std::declval>(), std::declval>()))); } TEST(set_value, rvalue_calls) { static_assert(std::invocable>); static_assert(std::invocable>, arg<0>>); + static_assert(std::invocable>, conv<0>>); static_assert(not std::invocable>, no_arg>); static_assert(std::invocable, arg<1>, arg<2>>, arg<0>, arg<1>, arg<2>>); + static_assert(std::invocable, arg<1>, arg<2>>, conv<0>, conv<1>, conv<2>>); static_assert(not std::invocable>); static_assert(not std::invocable&>); static_assert(not std::invocable&>); @@ -205,6 +247,13 @@ TEST(set_value, rvalue_calls) EXPECT_NE(called, nullptr); EXPECT_EQ(*called, std::make_tuple(&arg0)); } + { + std::tuple*>* called{nullptr}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(rvalue_receiver>{&called}, conv<0>{}); + EXPECT_NE(called, nullptr); + } { std::tuple*, arg<1>*, arg<2>*>* called{nullptr}; arg<0> arg0{}; @@ -216,6 +265,13 @@ TEST(set_value, rvalue_calls) EXPECT_NE(called, nullptr); EXPECT_EQ(*called, std::make_tuple(&arg0, &arg1, &arg2)); } + { + std::tuple*, arg<1>*, arg<2>*>* called{nullptr}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(rvalue_receiver, arg<1>, arg<2>>{&called}, conv<0>{}, conv<1>{}, conv<2>{}); + EXPECT_NE(called, nullptr); + } } TEST(set_value, lvalue_calls) @@ -225,18 +281,24 @@ TEST(set_value, lvalue_calls) static_assert(std::invocable&>); static_assert(std::invocable>&, arg<0>>); + static_assert(std::invocable>&, conv<0>>); static_assert(not std::invocable>&, no_arg>); static_assert(std::invocable, arg<1>, arg<2>>&, arg<0>, arg<1>, arg<2>>); + static_assert(std::invocable, arg<1>, arg<2>>&, conv<0>, conv<1>, conv<2>>); static_assert(not std::invocable&>); static_assert(not std::invocable>&, arg<0>>); + static_assert(not std::invocable>&, conv<0>>); static_assert(not std::invocable,arg<1>, arg<2>>&, arg<0>,arg<1>, arg<2>>); + static_assert(not std::invocable,arg<1>, arg<2>>&, conv<0>,conv<1>, conv<2>>); static_assert(not std::invocable const&>); static_assert(not std::invocable const&>); static_assert(noexcept(std::execution::set_value(std::declval&>()))); static_assert(noexcept(std::execution::set_value(std::declval&>&>(), std::declval&>()))); + static_assert(noexcept(std::execution::set_value(std::declval>&>(), std::declval>()))); static_assert(noexcept(std::execution::set_value(std::declval&, arg<1>&, arg<2>&>&>(), std::declval&>(), std::declval&>(), std::declval&>()))); + static_assert(noexcept(std::execution::set_value(std::declval, arg<1>, arg<2>>&>(), std::declval>(), std::declval>(), std::declval>()))); { std::tuple<>* called{nullptr}; @@ -255,6 +317,14 @@ TEST(set_value, lvalue_calls) EXPECT_NE(called, nullptr); EXPECT_EQ(*called, std::make_tuple(&arg0)); } + { + std::tuple*>* called{nullptr}; + lvalue_receiver> receiver{&called}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(receiver, conv<0>{}); + EXPECT_NE(called, nullptr); + } { std::tuple*, arg<1>*, arg<2>*>* called{nullptr}; lvalue_receiver&, arg<1>&, arg<2>&> receiver{&called}; @@ -267,6 +337,14 @@ TEST(set_value, lvalue_calls) EXPECT_NE(called, nullptr); EXPECT_EQ(*called, std::make_tuple(&arg0, &arg1, &arg2)); } + { + std::tuple*, arg<1>*, arg<2>*>* called{nullptr}; + lvalue_receiver, arg<1>, arg<2>> receiver{&called}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(receiver, conv<0>{}, conv<1>{}, conv<2>{}); + EXPECT_NE(called, nullptr); + } } // ---------------------------------------------------------------------------- @@ -275,32 +353,48 @@ TEST(set_value, const_calls) { static_assert(std::invocable>); static_assert(std::invocable>, arg<0>>); + static_assert(std::invocable>, conv<0>>); static_assert(std::invocable, arg<1>, arg<2>>, arg<0>, arg<1>, arg<2>>); + static_assert(std::invocable, arg<1>, arg<2>>, conv<0>, conv<1>, conv<2>>); static_assert(not std::invocable>); static_assert(not std::invocable>, arg<0>>); + static_assert(not std::invocable>, conv<0>>); static_assert(not std::invocable, arg<1>, arg<2>>, arg<0>, arg<1>, arg<2>>); + static_assert(not std::invocable, arg<1>, arg<2>>, conv<0>, conv<1>, conv<2>>); static_assert(std::invocable&>); static_assert(std::invocable>&, arg<0>>); + static_assert(std::invocable>&, conv<0>>); static_assert(std::invocable, arg<1>, arg<2>>&, arg<0>, arg<1>, arg<2>>); + static_assert(std::invocable, arg<1>, arg<2>>&, conv<0>, conv<1>, conv<2>>); static_assert(not std::invocable&>); static_assert(not std::invocable>&, arg<0>>); + static_assert(not std::invocable>&, conv<0>>); static_assert(not std::invocable, arg<1>, arg<2>>&, arg<0>, arg<1>, arg<2>>); + static_assert(not std::invocable, arg<1>, arg<2>>&, conv<0>, conv<1>, conv<2>>); static_assert(std::invocable const&>); static_assert(std::invocable> const&, arg<0>>); + static_assert(std::invocable> const&, conv<0>>); static_assert(std::invocable, arg<1>, arg<2>> const&, arg<0>, arg<1>, arg<2>>); + static_assert(std::invocable, arg<1>, arg<2>> const&, conv<0>, conv<1>, conv<2>>); static_assert(not std::invocable const&>); static_assert(not std::invocable> const&, arg<0>>); + static_assert(not std::invocable> const&, conv<0>>); static_assert(not std::invocable, arg<1>, arg<2>> const&, arg<0>, arg<1>, arg<2>>); + static_assert(not std::invocable, arg<1>, arg<2>> const&, conv<0>, conv<1>, conv<2>>); static_assert(noexcept(std::execution::set_value(std::declval>()))); static_assert(noexcept(std::execution::set_value(std::declval>>(), std::declval>()))); + static_assert(noexcept(std::execution::set_value(std::declval>>(), std::declval>()))); static_assert(noexcept(std::execution::set_value(std::declval, arg<1>, arg<2>>>(), std::declval>(), std::declval>(), std::declval>()))); + static_assert(noexcept(std::execution::set_value(std::declval, arg<1>, arg<2>>>(), std::declval>(), std::declval>(), std::declval>()))); static_assert(noexcept(std::execution::set_value(std::declval&>()))); static_assert(noexcept(std::execution::set_value(std::declval>&>(), std::declval>()))); + static_assert(noexcept(std::execution::set_value(std::declval>&>(), std::declval>()))); static_assert(noexcept(std::execution::set_value(std::declval, arg<1>, arg<2>>&>(), std::declval>(), std::declval>(), std::declval>()))); + static_assert(noexcept(std::execution::set_value(std::declval, arg<1>, arg<2>>&>(), std::declval>(), std::declval>(), std::declval>()))); { std::tuple<>* called{nullptr}; @@ -318,6 +412,13 @@ TEST(set_value, const_calls) EXPECT_NE(called, nullptr); EXPECT_EQ(*called, std::make_tuple(&arg0)); } + { + std::tuple*>* called{nullptr}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(const_receiver>{&called}, conv<0>{}); + EXPECT_NE(called, nullptr); + } { std::tuple*, arg<1>*, arg<2>*>* called{nullptr}; arg<0> arg0{}; @@ -329,6 +430,13 @@ TEST(set_value, const_calls) EXPECT_NE(called, nullptr); EXPECT_EQ(*called, std::make_tuple(&arg0, &arg1, &arg2)); } + { + std::tuple*, arg<1>*, arg<2>*>* called{nullptr}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(const_receiver, arg<1>, arg<2>>{&called}, conv<0>{}, conv<1>{}, conv<2>{}); + EXPECT_NE(called, nullptr); + } { std::tuple<>* called{nullptr}; @@ -348,6 +456,14 @@ TEST(set_value, const_calls) EXPECT_NE(called, nullptr); EXPECT_EQ(*called, std::make_tuple(&arg0)); } + { + std::tuple*>* called{nullptr}; + const_receiver> receiver{&called}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(receiver, conv<0>{}); + EXPECT_NE(called, nullptr); + } { std::tuple*, arg<1>*, arg<2>*>* called{nullptr}; const_receiver&, arg<1>&, arg<2>&> receiver{&called}; @@ -360,6 +476,14 @@ TEST(set_value, const_calls) EXPECT_NE(called, nullptr); EXPECT_EQ(*called, std::make_tuple(&arg0, &arg1, &arg2)); } + { + std::tuple*, arg<1>*, arg<2>*>* called{nullptr}; + const_receiver, arg<1>, arg<2>> receiver{&called}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(receiver, conv<0>{}, conv<1>{}, conv<2>{}); + EXPECT_NE(called, nullptr); + } { std::tuple<>* called{nullptr}; @@ -379,6 +503,14 @@ TEST(set_value, const_calls) EXPECT_NE(called, nullptr); EXPECT_EQ(*called, std::make_tuple(&arg0)); } + { + std::tuple*>* called{nullptr}; + const_receiver> const receiver{&called}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(receiver, conv<0>{}); + EXPECT_NE(called, nullptr); + } { std::tuple*, arg<1>*, arg<2>*>* called{nullptr}; const_receiver&, arg<1>&, arg<2>&> const receiver{&called}; @@ -391,4 +523,12 @@ TEST(set_value, const_calls) EXPECT_NE(called, nullptr); EXPECT_EQ(*called, std::make_tuple(&arg0, &arg1, &arg2)); } + { + std::tuple*, arg<1>*, arg<2>*>* called{nullptr}; + const_receiver, arg<1>, arg<2>> const receiver{&called}; + + ASSERT_EQ(called, nullptr); + std::execution::set_value(receiver, conv<0>{}, conv<1>{}, conv<2>{}); + EXPECT_NE(called, nullptr); + } } \ No newline at end of file