Skip to content
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
1 change: 1 addition & 0 deletions libcxx/docs/ReleaseNotes/19.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Implemented Papers
- P3142R0 - Printing Blank Lines with ``println`` (as DR against C++23)
- P2944R3 - Comparisons for ``reference_wrapper`` (comparison operators for ``reference_wrapper`` only)
- P2968R2 - Make ``std::ignore`` a first-class object
- P2997R1 - Removing the common reference requirement from the indirectly invocable concepts
- P2302R4 - ``std::ranges::contains``
- P1659R3 - ``std::ranges::starts_with`` and ``std::ranges::ends_with``
- P3029R1 - Better ``mdspan``'s CTAD
Expand Down
15 changes: 6 additions & 9 deletions libcxx/include/__iterator/concepts.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,46 +177,43 @@ concept __has_arrow = input_iterator<_Ip> && (is_pointer_v<_Ip> || requires(_Ip
template <class _Fp, class _It>
concept indirectly_unary_invocable =
indirectly_readable<_It> && copy_constructible<_Fp> && invocable<_Fp&, iter_value_t<_It>&> &&
invocable<_Fp&, iter_reference_t<_It>> && invocable<_Fp&, iter_common_reference_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>>>;

template <class _Fp, class _It>
concept indirectly_regular_unary_invocable =
indirectly_readable<_It> && copy_constructible<_Fp> && regular_invocable<_Fp&, iter_value_t<_It>&> &&
regular_invocable<_Fp&, iter_reference_t<_It>> && regular_invocable<_Fp&, iter_common_reference_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>>>;

template <class _Fp, class _It>
concept indirect_unary_predicate =
indirectly_readable<_It> && copy_constructible<_Fp> && predicate<_Fp&, iter_value_t<_It>&> &&
predicate<_Fp&, iter_reference_t<_It>> && predicate<_Fp&, iter_common_reference_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&, iter_reference_t<_It1>, iter_reference_t<_It2>> &&
predicate<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_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&, iter_reference_t<_It1>, iter_reference_t<_It2>> &&
equivalence_relation<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_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&, iter_reference_t<_It1>, iter_reference_t<_It2>> &&
strict_weak_order<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>;
strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>;

template <class _Fp, class... _Its>
requires(indirectly_readable<_Its> && ...) && invocable<_Fp, iter_reference_t<_Its>...>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ struct BadPredicate5 {
};
static_assert(!std::indirect_binary_predicate<BadPredicate5, It1, It2>);

// Should fail when the predicate can't be called with (iter_common_reference_t, iter_common_reference_t)
// This case was made valid by P2997R1.
struct BadPredicate6 {
template <class T, class U> bool operator()(T const&, U const&) const;
bool operator()(std::iter_common_reference_t<It1>, std::iter_common_reference_t<It2>) const = delete;
};
static_assert(!std::indirect_binary_predicate<BadPredicate6, It1, It2>);
static_assert(std::indirect_binary_predicate<BadPredicate6, It1, It2>);

// Test ADL-proofing (P2538R1)
#if TEST_STD_VER >= 26 || defined(_LIBCPP_VERSION)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,12 @@ struct BadRelation5 {
};
static_assert(!std::indirect_equivalence_relation<BadRelation5, It1, It2>);

// Should fail when the function can't be called with (iter_common_reference_t, iter_common_reference_t)
// This case was made valid by P2997R1.
struct BadRelation6 {
template <class T, class U> bool operator()(T const&, U const&) const;
bool operator()(std::iter_common_reference_t<It1>, std::iter_common_reference_t<It2>) const = delete;
};
static_assert(!std::indirect_equivalence_relation<BadRelation6, It1, It2>);
static_assert(std::indirect_equivalence_relation<BadRelation6, It1, It2>);

// Test ADL-proofing (P2538R1)
#if TEST_STD_VER >= 26 || defined(_LIBCPP_VERSION)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,12 @@ struct BadOrder5 {
};
static_assert(!std::indirect_strict_weak_order<BadOrder5, It1, It2>);

// Should fail when the function can't be called with (iter_common_reference_t, iter_common_reference_t)
// This case was made valid by P2997R1.
struct BadOrder6 {
template <class T, class U> bool operator()(T const&, U const&) const;
bool operator()(std::iter_common_reference_t<It1>, std::iter_common_reference_t<It2>) const = delete;
};
static_assert(!std::indirect_strict_weak_order<BadOrder6, It1, It2>);
static_assert(std::indirect_strict_weak_order<BadOrder6, It1, It2>);

// Test ADL-proofing (P2538R1)
#if TEST_STD_VER >= 26 || defined(_LIBCPP_VERSION)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ struct BadPredicate3 {
};
static_assert(!std::indirect_unary_predicate<BadPredicate3, It>);

// Should fail when the predicate can't be called with std::iter_common_reference_t<It>
// This case was made valid by P2997R1.
struct BadPredicate4 {
template <class T> bool operator()(T const&) const;
bool operator()(std::iter_common_reference_t<It>) const = delete;
};
static_assert(!std::indirect_unary_predicate<BadPredicate4, It>);
static_assert(std::indirect_unary_predicate<BadPredicate4, It>);

// Test ADL-proofing (P2538R1)
#if TEST_STD_VER >= 26 || defined(_LIBCPP_VERSION)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ struct BadInvocable3 {
};
static_assert(!std::indirectly_regular_unary_invocable<BadInvocable3, It>);

// Should fail when the invocable can't be called with (iter_common_reference_t)
// This case was made valid by P2997R1.
struct BadInvocable4 {
template <class T> R1 operator()(T const&) const;
R1 operator()(std::iter_common_reference_t<It>) const = delete;
};
static_assert(!std::indirectly_regular_unary_invocable<BadInvocable4, It>);
static_assert(std::indirectly_regular_unary_invocable<BadInvocable4, It>);

// Should fail when the invocable doesn't have a common reference between its return types
struct BadInvocable5 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ struct BadInvocable3 {
};
static_assert(!std::indirectly_unary_invocable<BadInvocable3, It>);

// Should fail when the invocable can't be called with (iter_common_reference_t)
// This case was made valid by P2997R1.
struct BadInvocable4 {
template <class T> R1 operator()(T const&) const;
R1 operator()(std::iter_common_reference_t<It>) const = delete;
};
static_assert(!std::indirectly_unary_invocable<BadInvocable4, It>);
static_assert(std::indirectly_unary_invocable<BadInvocable4, It>);

// Should fail when the invocable doesn't have a common reference between its return types
struct BadInvocable5 {
Expand Down
3 changes: 2 additions & 1 deletion libcxx/utils/generate_feature_test_macro_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,8 @@ def add_version_header(tc):
"name": "__cpp_lib_ranges",
"values": {
"c++20": 202207,
# "c++26": 202406, # P2997R1 Removing the common reference requirement from the indirectly invocable concepts
# "c++23": 202302, # Relaxing Ranges Just A Smidge
# "c++26": 202406, # P2997R1 Removing the common reference requirement from the indirectly invocable concepts
},
"headers": ["algorithm", "functional", "iterator", "memory", "ranges"],
},
Expand Down