Skip to content
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

[libc++] Implement views::join_with #65536

Open
wants to merge 38 commits into
base: main
Choose a base branch
from

Conversation

JMazurkiewicz
Copy link
Contributor

@JMazurkiewicz JMazurkiewicz commented Sep 6, 2023

@github-actions github-actions bot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Sep 6, 2023
@JMazurkiewicz JMazurkiewicz force-pushed the libcxx/ranges/join_with branch 5 times, most recently from 3259db4 to 0481670 Compare September 8, 2023 00:07
@JMazurkiewicz JMazurkiewicz force-pushed the libcxx/ranges/join_with branch from 0481670 to f113229 Compare September 8, 2023 15:11
@ldionne ldionne assigned var-const and huixie90 and unassigned var-const Sep 13, 2023
@ldionne ldionne requested a review from huixie90 September 15, 2023 20:55
@ldionne
Copy link
Member

ldionne commented Sep 15, 2023

@JMazurkiewicz Please ping us when this is ready to review and make it a non-draft.

@philnik777 philnik777 added the ranges Issues related to `<ranges>` label Oct 6, 2023
ldionne pushed a commit that referenced this pull request Oct 24, 2023
This patch adds a mention that the following papers are in progress:

* P2770R0: #66033
* P2441R2 and P2711R1: #65536
@JMazurkiewicz JMazurkiewicz force-pushed the libcxx/ranges/join_with branch from f113229 to 1835f68 Compare February 2, 2024 23:57
Copy link

github-actions bot commented Feb 3, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@JMazurkiewicz JMazurkiewicz marked this pull request as ready for review February 4, 2024 14:58
@JMazurkiewicz JMazurkiewicz requested a review from a team as a code owner February 4, 2024 14:58
@H-G-Hristov
Copy link
Contributor

H-G-Hristov commented May 10, 2024

I guess with constexpr variant this cool feature can be finalized now :)

@JMazurkiewicz JMazurkiewicz force-pushed the libcxx/ranges/join_with branch 3 times, most recently from a84985a to fcdf64a Compare May 14, 2024 14:38
@JMazurkiewicz JMazurkiewicz force-pushed the libcxx/ranges/join_with branch 3 times, most recently from 54a741c to a9a1031 Compare May 22, 2024 23:17
@JMazurkiewicz JMazurkiewicz force-pushed the libcxx/ranges/join_with branch from a9a1031 to 9406093 Compare June 5, 2024 09:49
_LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i)
requires _Const && convertible_to<iterator_t<_View>, _OuterIter> &&
convertible_to<iterator_t<_InnerRng>, _InnerIter> && convertible_to<iterator_t<_Pattern>, _PatternIter>
: __parent_(__i.__parent_), __outer_it_(std::move(__i.__outer_it_)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is something wrong. __iterator<false> is not a friend of __iterator<true>, so in theory this should not compile because of accessing private members.

This probably indicates that this function is not tested

Copy link
Contributor Author

@JMazurkiewicz JMazurkiewicz Jan 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is something wrong. __iterator<false> is not a friend of __iterator<true>, so in theory this should not compile because of accessing private members.

This probably indicates that this function is not tested

I think that everything is OK here. Even though __iterator<false> is not a friend of __iterator<true>, its members can still be accessed thanks to friend join_with_view declaration. Per [class.friend]/2:

Declaring a class to be a friend implies that private and protected members of the class granting friendship can be named in the base-specifiers and member declarations of the befriended class.

__iterator<false> declares join_with_view to be a friend, which means that member declarations of it (__iterator<true> and __sentinel<?>) can access iterator's private members.

auto it = jwv.begin();
assert(*it == 1);

using CIter = std::ranges::iterator_t<const decltype(jwv)>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please

static_assert(!std::is_same_v<Iter, CIter>);

I think this test is not testing what it is supposed to test. I suspect it and cit are both iterator<true>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added here: 14471bc


_LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __s)
requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
: __end_(std::move(__s.__end_)) {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as iterator, I think __sentinel<false> is not a friend of __sentinel<true> so this should not compile. And it is an indication of missing tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that [class.friend]/2 applies here too.

requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
return __x.__get_outer() == __y.__end_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again. __get_outer is private and I don't think sentinel has been befriended to iterator. This should not compile in theory. possible missing tests as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right here, operator== is a friend of sentinel only, so it should not be able to access iterator's private members. Unluckily, both clang and gcc accept this incorrect code.

Fixed here: 9760ec3


// <ranges>

// iterator() = default;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we usually have another test point to test this is not explicit.

Iter iter = {};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added here: 3771be9


// <ranges>

// friend constexpr void iter_swap(const iterator& x, const iterator& y);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we have a test to test that it delicates to underlying's tier_swap? i.e. not doing ranges::swap(*it1, *it2)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! 19e4fa2

std::ranges::join_with_view jwv(vec, 0);
using JWV = decltype(jwv);
static_assert(!std::ranges::common_range<JWV>);
using CSent = std::ranges::sentinel_t<const JWV>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we static_assert(!std::same_as<Sent, CSent>) to make sure we are testing what we are supposed to test

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added here: d52bdbf


// template<bool OtherConst>
// requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
// friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we make sure we static_assert(!same_as<Iter, CIter>) and static_assert(!same_as<Sent, CSent>) and make sure we test all the combinations

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added here: 96eae0b


// <ranges>

// join_with_view()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we usually have a test to test the explicitness

join_with_view<...> jwv = {};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added: 4ab1ee2

}
}

constexpr void test_end() {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not, I forgot to remove it earlier (fb5ab01).

@Zingam
Copy link
Contributor

Zingam commented Jan 18, 2025

@JMazurkiewicz At the top you mention that this PR completed several papers. Do you need to add additional GitHub issues to the list that this PR closes/fixes/?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. ranges Issues related to `<ranges>`
Projects
None yet
8 participants