Skip to content

[libc++][ranges] P2609R3: Relaxing Ranges Just A Smidge #101715

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion libcxx/docs/FeatureTestMacroTable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_polymorphic_allocator`` ``201902L``
---------------------------------------------------------- -----------------
``__cpp_lib_ranges`` ``202207L``
``__cpp_lib_ranges`` ``202110L``
---------------------------------------------------------- -----------------
``__cpp_lib_remove_cvref`` ``201711L``
---------------------------------------------------------- -----------------
Expand Down Expand Up @@ -350,6 +350,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_print`` ``202207L``
---------------------------------------------------------- -----------------
``__cpp_lib_ranges`` ``202406L``
---------------------------------------------------------- -----------------
``__cpp_lib_ranges_as_const`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_ranges_as_rvalue`` ``202207L``
Expand Down
1 change: 1 addition & 0 deletions libcxx/docs/ReleaseNotes/20.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ What's New in Libc++ 20.0.0?
Implemented Papers
------------------

- P2609R3: Relaxing Ranges Just A Smidge (`Github <https://github.com/llvm/llvm-project/issues/105253>`__)
- P2985R0: A type trait for detecting virtual base classes (`Github <https://github.com/llvm/llvm-project/issues/105432>`__)


Expand Down
1 change: 1 addition & 0 deletions libcxx/docs/Status/Cxx23.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Paper Status
.. [#note-P2520R0] P2520R0: Libc++ implemented this paper as a DR in C++20 as well.
.. [#note-P2711R1] P2711R1: ``join_with_view`` hasn't been done yet since this type isn't implemented yet.
.. [#note-P2770R0] P2770R0: ``join_with_view`` hasn't been done yet since this type isn't implemented yet.
.. [#note-P2609R3] P2609R3: Libc++ implemented this paper as a DR in C++20 as well. (MSVC STL does the same.)
.. [#note-LWG3494] LWG3494: That LWG issue was superseded by `P2017R1 <https://wg21.link/P2017R1>`__.
.. [#note-LWG3481] LWG3481: That LWG issue was superseded by `P2415R2 <https://wg21.link/P2415R2>`__.
.. [#note-LWG3265] LWG3265: That LWG issue was resolved by `LWG3435 <https://wg21.link/LWG3435>`__.
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx23Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
"`P2770R0 <https://wg21.link/P2770R0>`__","Stashing stashing ``iterators`` for proper flattening","2023-02 (Issaquah)","|Partial| [#note-P2770R0]_","","|ranges|"
"`P2164R9 <https://wg21.link/P2164R9>`__","``views::enumerate``","2023-02 (Issaquah)","","","|ranges|"
"`P2711R1 <https://wg21.link/P2711R1>`__","Making multi-param constructors of ``views`` ``explicit``","2023-02 (Issaquah)","|In Progress| [#note-P2711R1]_","","|ranges|"
"`P2609R3 <https://wg21.link/P2609R3>`__","Relaxing Ranges Just A Smidge","2023-02 (Issaquah)","","","|ranges|"
"`P2609R3 <https://wg21.link/P2609R3>`__","Relaxing Ranges Just A Smidge","2023-02 (Issaquah)","|Complete| [#note-P2609R3]_","20.0","|ranges|"
"`P2713R1 <https://wg21.link/P2713R1>`__","Escaping improvements in ``std::format``","2023-02 (Issaquah)","|Complete|","19.0","|format|"
"`P2675R1 <https://wg21.link/P2675R1>`__","``format``'s width estimation is too approximate and not forward compatible","2023-02 (Issaquah)","|Complete|","17.0","|format|"
"`P2572R1 <https://wg21.link/P2572R1>`__","``std::format`` fill character allowances","2023-02 (Issaquah)","|Complete|","17.0","|format|"
Expand Down
58 changes: 43 additions & 15 deletions libcxx/include/__iterator/concepts.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <__type_traits/add_pointer.h>
#include <__type_traits/common_reference.h>
#include <__type_traits/is_pointer.h>
#include <__type_traits/is_primary_template.h>
#include <__type_traits/is_reference.h>
#include <__type_traits/remove_cv.h>
#include <__type_traits/remove_cvref.h>
Expand Down Expand Up @@ -64,8 +65,33 @@ concept __indirectly_readable_impl =
template <class _In>
concept indirectly_readable = __indirectly_readable_impl<remove_cvref_t<_In>>;

template <class _Tp>
using __projected_iterator_t = typename _Tp::__projected_iterator;

template <class _Tp>
using __projected_projection_t = typename _Tp::__projected_projection;

template <class _Tp>
concept __specialization_of_projected = requires {
typename __projected_iterator_t<_Tp>;
typename __projected_projection_t<_Tp>;
} && __is_primary_template<_Tp>::value;

template <class _Tp>
struct __indirect_value_t_impl {
using type = iter_value_t<_Tp>&;
};
template <__specialization_of_projected _Tp>
struct __indirect_value_t_impl<_Tp> {
using type = invoke_result_t<__projected_projection_t<_Tp>&,
typename __indirect_value_t_impl<__projected_iterator_t<_Tp>>::type>;
};

template <indirectly_readable _Tp>
using __indirect_value_t = typename __indirect_value_t_impl<_Tp>::type;

template <indirectly_readable _Tp>
using iter_common_reference_t = common_reference_t<iter_reference_t<_Tp>, iter_value_t<_Tp>&>;
using iter_common_reference_t = common_reference_t<iter_reference_t<_Tp>, __indirect_value_t<_Tp>>;

// [iterator.concept.writable]
template <class _Out, class _Tp>
Expand Down Expand Up @@ -176,43 +202,45 @@ concept __has_arrow = input_iterator<_Ip> && (is_pointer_v<_Ip> || requires(_Ip
// [indirectcallable.indirectinvocable]
template <class _Fp, class _It>
concept indirectly_unary_invocable =
indirectly_readable<_It> && copy_constructible<_Fp> && invocable<_Fp&, iter_value_t<_It>&> &&
indirectly_readable<_It> && copy_constructible<_Fp> && invocable<_Fp&, __indirect_value_t<_It>> &&
invocable<_Fp&, iter_reference_t<_It>> &&
common_reference_with< invoke_result_t<_Fp&, iter_value_t<_It>&>, invoke_result_t<_Fp&, iter_reference_t<_It>>>;
common_reference_with< invoke_result_t<_Fp&, __indirect_value_t<_It>>,
invoke_result_t<_Fp&, iter_reference_t<_It>>>;

template <class _Fp, class _It>
concept indirectly_regular_unary_invocable =
indirectly_readable<_It> && copy_constructible<_Fp> && regular_invocable<_Fp&, iter_value_t<_It>&> &&
indirectly_readable<_It> && copy_constructible<_Fp> && regular_invocable<_Fp&, __indirect_value_t<_It>> &&
regular_invocable<_Fp&, iter_reference_t<_It>> &&
common_reference_with< invoke_result_t<_Fp&, iter_value_t<_It>&>, invoke_result_t<_Fp&, iter_reference_t<_It>>>;
common_reference_with< invoke_result_t<_Fp&, __indirect_value_t<_It>>,
invoke_result_t<_Fp&, iter_reference_t<_It>>>;

template <class _Fp, class _It>
concept indirect_unary_predicate =
indirectly_readable<_It> && copy_constructible<_Fp> && predicate<_Fp&, iter_value_t<_It>&> &&
indirectly_readable<_It> && copy_constructible<_Fp> && predicate<_Fp&, __indirect_value_t<_It>> &&
predicate<_Fp&, iter_reference_t<_It>>;

template <class _Fp, class _It1, class _It2>
concept indirect_binary_predicate =
indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fp> &&
predicate<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> &&
predicate<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> &&
predicate<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> &&
predicate<_Fp&, __indirect_value_t<_It1>, __indirect_value_t<_It2>> &&
predicate<_Fp&, __indirect_value_t<_It1>, iter_reference_t<_It2>> &&
predicate<_Fp&, iter_reference_t<_It1>, __indirect_value_t<_It2>> &&
predicate<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>;

template <class _Fp, class _It1, class _It2 = _It1>
concept indirect_equivalence_relation =
indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fp> &&
equivalence_relation<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> &&
equivalence_relation<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> &&
equivalence_relation<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> &&
equivalence_relation<_Fp&, __indirect_value_t<_It1>, __indirect_value_t<_It2>> &&
equivalence_relation<_Fp&, __indirect_value_t<_It1>, iter_reference_t<_It2>> &&
equivalence_relation<_Fp&, iter_reference_t<_It1>, __indirect_value_t<_It2>> &&
equivalence_relation<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>;

template <class _Fp, class _It1, class _It2 = _It1>
concept indirect_strict_weak_order =
indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fp> &&
strict_weak_order<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> &&
strict_weak_order<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> &&
strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> &&
strict_weak_order<_Fp&, __indirect_value_t<_It1>, __indirect_value_t<_It2>> &&
strict_weak_order<_Fp&, __indirect_value_t<_It1>, iter_reference_t<_It2>> &&
strict_weak_order<_Fp&, iter_reference_t<_It1>, __indirect_value_t<_It2>> &&
strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>;

template <class _Fp, class... _Its>
Expand Down
8 changes: 8 additions & 0 deletions libcxx/include/__iterator/projected.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _It, class _Proj>
struct __projected_impl {
struct __type {
using __primary_template = __type;
using __projected_iterator = _It;
using __projected_projection = _Proj;

using value_type = remove_cvref_t<indirect_result_t<_Proj&, _It>>;
indirect_result_t<_Proj&, _It> operator*() const; // not defined
};
Expand All @@ -34,6 +38,10 @@ struct __projected_impl {
template <weakly_incrementable _It, class _Proj>
struct __projected_impl<_It, _Proj> {
struct __type {
using __primary_template = __type;
using __projected_iterator = _It;
using __projected_projection = _Proj;

using value_type = remove_cvref_t<indirect_result_t<_Proj&, _It>>;
using difference_type = iter_difference_t<_It>;
indirect_result_t<_Proj&, _It> operator*() const; // not defined
Expand Down
7 changes: 5 additions & 2 deletions libcxx/include/version
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,9 @@ __cpp_lib_philox_engine 202406L <random>
__cpp_lib_polymorphic_allocator 201902L <memory_resource>
__cpp_lib_print 202207L <ostream> <print>
__cpp_lib_quoted_string_io 201304L <iomanip>
__cpp_lib_ranges 202207L <algorithm> <functional> <iterator>
__cpp_lib_ranges 202406L <algorithm> <functional> <iterator>
<memory> <ranges>
202110L // C++20
__cpp_lib_ranges_as_const 202207L <ranges>
__cpp_lib_ranges_as_rvalue 202207L <ranges>
__cpp_lib_ranges_chunk 202202L <ranges>
Expand Down Expand Up @@ -428,7 +429,7 @@ __cpp_lib_void_t 201411L <type_traits>
# if _LIBCPP_AVAILABILITY_HAS_PMR
# define __cpp_lib_polymorphic_allocator 201902L
# endif
# define __cpp_lib_ranges 202207L
# define __cpp_lib_ranges 202110L
# define __cpp_lib_remove_cvref 201711L
# if !defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC
# define __cpp_lib_semaphore 201907L
Expand Down Expand Up @@ -480,6 +481,8 @@ __cpp_lib_void_t 201411L <type_traits>
# define __cpp_lib_optional 202110L
# define __cpp_lib_out_ptr 202106L
# define __cpp_lib_print 202207L
# undef __cpp_lib_ranges
# define __cpp_lib_ranges 202406L
// # define __cpp_lib_ranges_as_const 202207L
# define __cpp_lib_ranges_as_rvalue 202207L
// # define __cpp_lib_ranges_chunk 202202L
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17

// template<indirectly_readable T>
// using indirect-value-t = see below; // exposition only

#include <algorithm>
#include <memory>
#include <ranges>
#include <utility>
#include <vector>

void test() {
auto ints = std::views::iota(0, 5);
auto unique_ptr_maker = []<std::movable T>(T v) { return std::make_unique<T>(std::move(v)); };

using iota_iter = std::ranges::iterator_t<decltype(ints)>;
using unique_ptr_projection = decltype(unique_ptr_maker);
using projected_iter = std::projected<iota_iter, unique_ptr_projection>;

{ // Check std::indirectly_unary_invocable
auto consume = [](auto) {};
static_assert(std::indirectly_unary_invocable<decltype(consume), projected_iter>);

std::ranges::for_each(ints, consume, unique_ptr_maker);
std::ranges::for_each(ints.begin(), ints.end(), consume, unique_ptr_maker);
}

{ // Check std::indirectly_regular_unary_invocable
static_assert(std::indirectly_regular_unary_invocable<decltype([](auto) {}), projected_iter>);
using check_wellformedness [[maybe_unused]] = std::projected<projected_iter, unique_ptr_projection>;
}

{ // Check std::indirect_unary_predicate
auto unary_pred = [](auto) { return false; };
static_assert(std::indirect_unary_predicate<decltype(unary_pred), projected_iter>);

(void)std::ranges::find_if(ints, unary_pred, unique_ptr_maker);
(void)std::ranges::find_if(ints.begin(), ints.end(), unary_pred, unique_ptr_maker);
(void)std::ranges::count_if(ints, unary_pred, unique_ptr_maker);
(void)std::ranges::count_if(ints.begin(), ints.end(), unary_pred, unique_ptr_maker);
}

{ // Check std::indirect_binary_predicate
auto binary_pred = [](auto, auto) { return false; };
static_assert(std::indirect_binary_predicate<decltype(binary_pred), projected_iter, projected_iter>);

(void)std::ranges::adjacent_find(ints, binary_pred, unique_ptr_maker);
(void)std::ranges::adjacent_find(ints.begin(), ints.end(), binary_pred, unique_ptr_maker);
}

{ // Check std::indirect_equivalence_relation
auto rel = [](auto, auto) { return false; };
static_assert(std::indirect_equivalence_relation<decltype(rel), projected_iter>);

std::vector<int> out;
(void)std::ranges::unique_copy(ints, std::back_inserter(out), rel, unique_ptr_maker);
(void)std::ranges::unique_copy(ints.begin(), ints.end(), std::back_inserter(out), rel, unique_ptr_maker);
}

{ // Check std::indirect_strict_weak_order
auto rel = [](auto x, auto y) { return x < y; };
static_assert(std::indirect_strict_weak_order<decltype(rel), projected_iter>);

(void)std::ranges::is_sorted_until(ints, rel, unique_ptr_maker);
(void)std::ranges::is_sorted_until(ints.begin(), ints.end(), rel, unique_ptr_maker);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
__cpp_lib_default_template_type_for_algorithm_values 202403L [C++26]
__cpp_lib_freestanding_algorithm 202311L [C++26]
__cpp_lib_parallel_algorithm 201603L [C++17]
__cpp_lib_ranges 202207L [C++20]
__cpp_lib_ranges 202110L [C++20]
202406L [C++23]
__cpp_lib_ranges_contains 202207L [C++23]
__cpp_lib_ranges_find_last 202207L [C++23]
__cpp_lib_ranges_starts_ends_with 202106L [C++23]
Expand Down Expand Up @@ -244,8 +245,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++20"
# endif
# if __cpp_lib_ranges != 202207L
# error "__cpp_lib_ranges should have the value 202207L in c++20"
# if __cpp_lib_ranges != 202110L
# error "__cpp_lib_ranges should have the value 202110L in c++20"
# endif

# ifdef __cpp_lib_ranges_contains
Expand Down Expand Up @@ -321,8 +322,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++23"
# endif
# if __cpp_lib_ranges != 202207L
# error "__cpp_lib_ranges should have the value 202207L in c++23"
# if __cpp_lib_ranges != 202406L
# error "__cpp_lib_ranges should have the value 202406L in c++23"
# endif

# ifndef __cpp_lib_ranges_contains
Expand Down Expand Up @@ -425,8 +426,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++26"
# endif
# if __cpp_lib_ranges != 202207L
# error "__cpp_lib_ranges should have the value 202207L in c++26"
# if __cpp_lib_ranges != 202406L
# error "__cpp_lib_ranges should have the value 202406L in c++26"
# endif

# ifndef __cpp_lib_ranges_contains
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
__cpp_lib_invoke_r 202106L [C++23]
__cpp_lib_move_only_function 202110L [C++23]
__cpp_lib_not_fn 201603L [C++17]
__cpp_lib_ranges 202207L [C++20]
__cpp_lib_ranges 202110L [C++20]
202406L [C++23]
__cpp_lib_reference_wrapper 202403L [C++26]
__cpp_lib_result_of_sfinae 201210L [C++14]
__cpp_lib_transparent_operators 201210L [C++14]
Expand Down Expand Up @@ -305,8 +306,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++20"
# endif
# if __cpp_lib_ranges != 202207L
# error "__cpp_lib_ranges should have the value 202207L in c++20"
# if __cpp_lib_ranges != 202110L
# error "__cpp_lib_ranges should have the value 202110L in c++20"
# endif

# ifdef __cpp_lib_reference_wrapper
Expand Down Expand Up @@ -409,8 +410,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++23"
# endif
# if __cpp_lib_ranges != 202207L
# error "__cpp_lib_ranges should have the value 202207L in c++23"
# if __cpp_lib_ranges != 202406L
# error "__cpp_lib_ranges should have the value 202406L in c++23"
# endif

# ifdef __cpp_lib_reference_wrapper
Expand Down Expand Up @@ -531,8 +532,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++26"
# endif
# if __cpp_lib_ranges != 202207L
# error "__cpp_lib_ranges should have the value 202207L in c++26"
# if __cpp_lib_ranges != 202406L
# error "__cpp_lib_ranges should have the value 202406L in c++26"
# endif

# ifndef __cpp_lib_reference_wrapper
Expand Down
Loading
Loading