From 6ab889747b369ee4bb4ec41ee41e7448a2d17619 Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Mon, 20 Feb 2023 16:00:12 +0100 Subject: [PATCH 1/7] Feature test macro --- stl/inc/yvals_core.h | 3 ++- .../VSO_0157762_feature_test_macros/test.compile.pass.cpp | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index ce8d39dcec..2b4e94d4aa 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -352,6 +352,7 @@ // P2505R5 Monadic Functions For expected // P2549R1 unexpected::error() // P2602R2 Poison Pills Are Too Toxic +// P2609R3 Relaxing Ranges Just A Smidge // Parallel Algorithms Notes // C++ allows an implementation to implement parallel algorithms as calls to the serial algorithms. @@ -1762,7 +1763,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #if defined(__cpp_lib_concepts) // TRANSITION, GH-395 #if _HAS_CXX23 -#define __cpp_lib_ranges 202211L // P2602R2 Poison Pills Are Too Toxic +#define __cpp_lib_ranges 202302L // P2609R3 Relaxing Ranges Just A Smidge #elif _HAS_CXX20 // ^^^ _HAS_CXX23 / _HAS_CXX20 vvv #define __cpp_lib_ranges 202110L // P2415R2 What Is A view? #endif // _HAS_CXX20 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 b1e028a2b1..9b3d6dc7ce 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 @@ -1507,10 +1507,10 @@ STATIC_ASSERT(__cpp_lib_quoted_string_io == 201304L); #if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 #ifndef __cpp_lib_ranges #error __cpp_lib_ranges is not defined -#elif __cpp_lib_ranges != 202211L -#error __cpp_lib_ranges is not 202211L +#elif __cpp_lib_ranges != 202302L +#error __cpp_lib_ranges is not 202302L #else -STATIC_ASSERT(__cpp_lib_ranges == 202211L); +STATIC_ASSERT(__cpp_lib_ranges == 202302L); #endif #elif _HAS_CXX20 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 #ifndef __cpp_lib_ranges From 3742489f42682611c294d481d7389913f1b6ad83 Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Mon, 20 Feb 2023 16:07:10 +0100 Subject: [PATCH 2/7] Relax concepts --- stl/inc/xutility | 109 ++++++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index c53c060d24..afe2884406 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -493,24 +493,33 @@ _EXPORT_STD template { _RANGES iter_move(__t) } -> _Can_reference; } using iter_rvalue_reference_t = decltype(_RANGES iter_move(_STD declval<_Ty&>())); +// clang-format on template -concept _Indirectly_readable_impl = requires(const _It __i) { - typename iter_value_t<_It>; - typename iter_reference_t<_It>; - typename iter_rvalue_reference_t<_It>; - { *__i } -> same_as>; - { _RANGES iter_move(__i) } -> same_as>; -} && common_reference_with&&, iter_value_t<_It>&> - && common_reference_with&&, iter_rvalue_reference_t<_It>&&> - && common_reference_with&&, const iter_value_t<_It>&>; +concept _Indirectly_readable_impl = + requires(const _It __i) { + typename iter_value_t<_It>; + typename iter_reference_t<_It>; + typename iter_rvalue_reference_t<_It>; + { *__i } -> same_as>; + { _RANGES iter_move(__i) } -> same_as>; + } && common_reference_with&&, iter_value_t<_It>&> + && common_reference_with&&, iter_rvalue_reference_t<_It>&&> + && common_reference_with&&, const iter_value_t<_It>&>; _EXPORT_STD template concept indirectly_readable = _Indirectly_readable_impl>; -// clang-format on + +template +struct _Indirect_value_impl { + using type = iter_value_t<_Ty>&; +}; + +template +using _Indirect_value_t = typename _Indirect_value_impl<_It>::type; _EXPORT_STD template -using iter_common_reference_t = common_reference_t, iter_value_t<_Ty>&>; +using iter_common_reference_t = common_reference_t, _Indirect_value_t<_Ty>>; _EXPORT_STD template concept indirectly_writable = @@ -629,69 +638,56 @@ concept contiguous_iterator = random_access_iterator<_It> && requires(const _It& __i) { { _STD to_address(__i) } -> same_as>>; }; +// clang-format on _EXPORT_STD template -concept indirectly_unary_invocable = indirectly_readable<_It> - && copy_constructible<_Fn> - && invocable<_Fn&, iter_value_t<_It>&> - && invocable<_Fn&, iter_reference_t<_It>> - && invocable<_Fn&, iter_common_reference_t<_It>> - && common_reference_with< - invoke_result_t<_Fn&, iter_value_t<_It>&>, +concept indirectly_unary_invocable = + indirectly_readable<_It> && copy_constructible<_Fn> && invocable<_Fn&, _Indirect_value_t<_It>> + && invocable<_Fn&, iter_reference_t<_It>> && invocable<_Fn&, iter_common_reference_t<_It>> + && common_reference_with>, invoke_result_t<_Fn&, iter_reference_t<_It>>>; _EXPORT_STD template -concept indirectly_regular_unary_invocable = indirectly_readable<_It> - && copy_constructible<_Fn> - && regular_invocable<_Fn&, iter_value_t<_It>&> - && regular_invocable<_Fn&, iter_reference_t<_It>> - && regular_invocable<_Fn&, iter_common_reference_t<_It>> - && common_reference_with< - invoke_result_t<_Fn&, iter_value_t<_It>&>, +concept indirectly_regular_unary_invocable = + indirectly_readable<_It> && copy_constructible<_Fn> && regular_invocable<_Fn&, _Indirect_value_t<_It>> + && regular_invocable<_Fn&, iter_reference_t<_It>> && regular_invocable<_Fn&, iter_common_reference_t<_It>> + && common_reference_with>, invoke_result_t<_Fn&, iter_reference_t<_It>>>; _EXPORT_STD template -concept indirect_unary_predicate = indirectly_readable<_It> - && copy_constructible<_Fn> - && predicate<_Fn&, iter_value_t<_It>&> - && predicate<_Fn&, iter_reference_t<_It>> - && predicate<_Fn&, iter_common_reference_t<_It>>; +concept indirect_unary_predicate = + indirectly_readable<_It> && copy_constructible<_Fn> && predicate<_Fn&, _Indirect_value_t<_It>> + && predicate<_Fn&, iter_reference_t<_It>> && predicate<_Fn&, iter_common_reference_t<_It>>; _EXPORT_STD template -concept indirect_binary_predicate = indirectly_readable<_It1> - && indirectly_readable<_It2> - && copy_constructible<_Fn> - && predicate<_Fn&, iter_value_t<_It1>&, iter_value_t<_It2>&> - && predicate<_Fn&, iter_value_t<_It1>&, iter_reference_t<_It2>> - && predicate<_Fn&, iter_reference_t<_It1>, iter_value_t<_It2>&> - && predicate<_Fn&, iter_reference_t<_It1>, iter_reference_t<_It2>> - && predicate<_Fn&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; +concept indirect_binary_predicate = indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fn> + && predicate<_Fn&, _Indirect_value_t<_It1>, _Indirect_value_t<_It2>> + && predicate<_Fn&, _Indirect_value_t<_It1>, iter_reference_t<_It2>> + && predicate<_Fn&, iter_reference_t<_It1>, _Indirect_value_t<_It2>> + && predicate<_Fn&, iter_reference_t<_It1>, iter_reference_t<_It2>> + && predicate<_Fn&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; _EXPORT_STD template -concept indirect_equivalence_relation = indirectly_readable<_It1> - && indirectly_readable<_It2> - && copy_constructible<_Fn> - && equivalence_relation<_Fn&, iter_value_t<_It1>&, iter_value_t<_It2>&> - && equivalence_relation<_Fn&, iter_value_t<_It1>&, iter_reference_t<_It2>> - && equivalence_relation<_Fn&, iter_reference_t<_It1>, iter_value_t<_It2>&> +concept indirect_equivalence_relation = + indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fn> + && equivalence_relation<_Fn&, _Indirect_value_t<_It1>, _Indirect_value_t<_It2>> + && equivalence_relation<_Fn&, _Indirect_value_t<_It1>, iter_reference_t<_It2>> + && equivalence_relation<_Fn&, iter_reference_t<_It1>, _Indirect_value_t<_It2>> && equivalence_relation<_Fn&, iter_reference_t<_It1>, iter_reference_t<_It2>> && equivalence_relation<_Fn&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; _EXPORT_STD template -concept indirect_strict_weak_order = indirectly_readable<_It1> - && indirectly_readable<_It2> - && copy_constructible<_Fn> - && strict_weak_order<_Fn&, iter_value_t<_It1>&, iter_value_t<_It2>&> - && strict_weak_order<_Fn&, iter_value_t<_It1>&, iter_reference_t<_It2>> - && strict_weak_order<_Fn&, iter_reference_t<_It1>, iter_value_t<_It2>&> +concept indirect_strict_weak_order = + indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fn> + && strict_weak_order<_Fn&, _Indirect_value_t<_It1>, _Indirect_value_t<_It2>> + && strict_weak_order<_Fn&, _Indirect_value_t<_It1>, iter_reference_t<_It2>> + && strict_weak_order<_Fn&, iter_reference_t<_It1>, _Indirect_value_t<_It2>> && strict_weak_order<_Fn&, iter_reference_t<_It1>, iter_reference_t<_It2>> && strict_weak_order<_Fn&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; _EXPORT_STD template - requires (indirectly_readable<_Its> && ...) - && invocable<_Fn, iter_reference_t<_Its>...> + requires (indirectly_readable<_Its> && ...) && invocable<_Fn, iter_reference_t<_Its>...> using indirect_result_t = invoke_result_t<_Fn, iter_reference_t<_Its>...>; -// clang-format on _EXPORT_STD template _Proj> struct projected { @@ -701,6 +697,13 @@ struct projected { } }; +#if _HAS_CXX23 +template +struct _Indirect_value_impl> { + using type = invoke_result_t<_Proj&, _Indirect_value_t<_It>>; +}; +#endif // _HAS_CXX23 + template struct incrementable_traits> { using difference_type = iter_difference_t<_It>; From 475f1b0b30eae5fa007ef8ce51e55f241da21625 Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Mon, 20 Feb 2023 16:45:22 +0100 Subject: [PATCH 3/7] Tests --- tests/std/test.lst | 1 + .../env.lst | 4 ++ .../test.compile.pass.cpp | 67 +++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/env.lst create mode 100644 tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp diff --git a/tests/std/test.lst b/tests/std/test.lst index dc8519a3ce..22e1b45d8f 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -592,6 +592,7 @@ tests\P2474R2_views_repeat_death tests\P2494R2_move_only_range_adaptors tests\P2505R5_monadic_functions_for_std_expected tests\P2517R1_apply_conditional_noexcept +tests\P2609R3_relaxing_ranges_just_a_smidge tests\VSO_0000000_allocator_propagation tests\VSO_0000000_any_calling_conventions tests\VSO_0000000_c_math_functions diff --git a/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/env.lst b/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/env.lst new file mode 100644 index 0000000000..18e2d7c71e --- /dev/null +++ b/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\concepts_latest_matrix.lst diff --git a/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp b/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp new file mode 100644 index 0000000000..e6f5675211 --- /dev/null +++ b/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +using namespace std; + +int main() { + auto ints = views::iota(0, 5); + auto project_to_unique_ptr = [](T v) { return make_unique(move(v)); }; + + using It = ranges::iterator_t; + using Proj = decltype(project_to_unique_ptr); + using ProjectedIt = projected; + + { // Check indirectly_unary_invocable + auto consume = [](auto) {}; + static_assert(indirectly_unary_invocable); + + ranges::for_each(ints, consume, project_to_unique_ptr); + ranges::for_each(ints.begin(), ints.end(), consume, project_to_unique_ptr); + } + + { // Check indirectly_regular_unary_invocable + static_assert(indirectly_regular_unary_invocable); + using Check [[maybe_unused]] = projected; + } + + { // Check indirect_unary_predicate + auto unary_pred = [](auto) { return false; }; + static_assert(indirect_unary_predicate); + + (void) ranges::find_if(ints, unary_pred, project_to_unique_ptr); + (void) ranges::find_if(ints.begin(), ints.end(), unary_pred, project_to_unique_ptr); + (void) ranges::count_if(ints, unary_pred, project_to_unique_ptr); + (void) ranges::count_if(ints.begin(), ints.end(), unary_pred, project_to_unique_ptr); + } + + { // Check indirect_binary_predicate + auto binary_pred = [](auto, auto) { return false; }; + static_assert(indirect_binary_predicate); + + (void) ranges::adjacent_find(ints, binary_pred, project_to_unique_ptr); + (void) ranges::adjacent_find(ints.begin(), ints.end(), binary_pred, project_to_unique_ptr); + } + + { // Check indirect_equivalence_relation + auto rel = [](auto, auto) { return false; }; + static_assert(indirect_equivalence_relation); + + vector out; + (void) ranges::unique_copy(ints, back_inserter(out), rel, project_to_unique_ptr); + (void) ranges::unique_copy(ints.begin(), ints.end(), back_inserter(out), rel, project_to_unique_ptr); + } + + { // Check indirect_strict_weak_order + auto rel = [](auto x, auto y) { return x < y; }; + static_assert(indirect_strict_weak_order); + + (void) ranges::is_sorted_until(ints, rel, project_to_unique_ptr); + (void) ranges::is_sorted_until(ints.begin(), ints.end(), rel, project_to_unique_ptr); + } +} From b70c4745bfa0eef688e1e3368b806bc47f35f749 Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Mon, 20 Feb 2023 18:51:15 +0100 Subject: [PATCH 4/7] Remove `` include and add missing `` for `std::move` --- .../P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp b/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp index e6f5675211..cbb9529e04 100644 --- a/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp +++ b/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp @@ -2,9 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include -#include #include #include +#include #include using namespace std; From 2688a3184e0d0d73b1bafd6ece810c12d20a0d24 Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Mon, 20 Feb 2023 18:52:39 +0100 Subject: [PATCH 5/7] Rename `int main` to `void test` With assumption that we don't need `int main() {} // COMPILE-ONLY` anymore thanks to https://github.com/microsoft/STL/pull/3484 --- .../P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp b/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp index cbb9529e04..5d57fe1688 100644 --- a/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp +++ b/tests/std/tests/P2609R3_relaxing_ranges_just_a_smidge/test.compile.pass.cpp @@ -9,7 +9,7 @@ using namespace std; -int main() { +void test() { auto ints = views::iota(0, 5); auto project_to_unique_ptr = [](T v) { return make_unique(move(v)); }; From 8554f2fbaa36996c3593b1d09bb80c4c3c38ed64 Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Mon, 20 Feb 2023 18:56:49 +0100 Subject: [PATCH 6/7] Implement P2609R3 in C++20 mode too See https://github.com/microsoft/STL/pull/3486#discussion_r1112178364 --- stl/inc/xutility | 2 -- 1 file changed, 2 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index afe2884406..3380536a2c 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -697,12 +697,10 @@ struct projected { } }; -#if _HAS_CXX23 template struct _Indirect_value_impl> { using type = invoke_result_t<_Proj&, _Indirect_value_t<_It>>; }; -#endif // _HAS_CXX23 template struct incrementable_traits> { From febff349c9440fe0304108c1e040469f1aa092b2 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 20 Feb 2023 13:57:09 -0800 Subject: [PATCH 7/7] This and P2606R2 are implemented in C++20 mode --- stl/inc/yvals_core.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 2b4e94d4aa..bbe345b0db 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -286,6 +286,8 @@ // P2508R1 basic_format_string, format_string, wformat_string // P2520R0 move_iterator Should Be A Random-Access Iterator // P2588R3 barrier's Phase Completion Guarantees +// P2602R2 Poison Pills Are Too Toxic +// P2609R3 Relaxing Ranges Just A Smidge // P2711R1 Making Multi-Param Constructors Of Views explicit // _HAS_CXX20 indirectly controls: @@ -351,8 +353,6 @@ // P2499R0 string_view Range Constructor Should Be explicit // P2505R5 Monadic Functions For expected // P2549R1 unexpected::error() -// P2602R2 Poison Pills Are Too Toxic -// P2609R3 Relaxing Ranges Just A Smidge // Parallel Algorithms Notes // C++ allows an implementation to implement parallel algorithms as calls to the serial algorithms.