diff --git a/stl/inc/xutility b/stl/inc/xutility index c53c060d24..3380536a2c 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,11 @@ struct projected { } }; +template +struct _Indirect_value_impl> { + using type = invoke_result_t<_Proj&, _Indirect_value_t<_It>>; +}; + template struct incrementable_traits> { using difference_type = iter_difference_t<_It>; diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index ce8d39dcec..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,7 +353,6 @@ // P2499R0 string_view Range Constructor Should Be explicit // P2505R5 Monadic Functions For expected // P2549R1 unexpected::error() -// P2602R2 Poison Pills Are Too Toxic // 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/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..5d57fe1688 --- /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; + +void test() { + 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); + } +} 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