This is an archive of the discontinued LLVM Phabricator instance.

[libcxx][ranges] revert join_view::iterator and sentinel to be in-class
ClosedPublic

Authored by huixie90 on Jan 28 2023, 7:45 AM.

Details

Summary

[libc++][ranges] revert join_view::iterator and sentinel to be in-class

  • inside the __iterator, having a member typedef using flag = __iterator and checks same_as<Tp::flag, Tp>. This way we can detect the class is indeed __iterator rather than a derived class.

Diff Detail

Event Timeline

huixie90 created this revision.Jan 28 2023, 7:45 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 28 2023, 7:45 AM
huixie90 published this revision for review.Jan 29 2023, 6:26 AM
huixie90 edited the summary of this revision. (Show Details)
huixie90 added reviewers: ldionne, philnik, var-const.
Herald added a project: Restricted Project. · View Herald TranscriptJan 29 2023, 6:26 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript
philnik added inline comments.Jan 29 2023, 6:50 AM
libcxx/include/__ranges/join_view.h
184

This seems quite complicated. Is there a reason not to use __is_primary_template instead?

huixie90 updated this revision to Diff 493097.Jan 29 2023, 8:16 AM

work around Clang 14 bug

huixie90 added inline comments.Jan 29 2023, 9:48 AM
libcxx/include/__ranges/join_view.h
184

I think the idea is exactly the same (the sfinae technique is also exactly the same but I did not know it is abstracted in _IsValidExpansion). but __is_primary_template does not sound the right name

huixie90 updated this revision to Diff 493107.Jan 29 2023, 9:59 AM

use _IsValidExpansion

ldionne added inline comments.Jan 30 2023, 6:45 AM
libcxx/include/__ranges/join_view.h
184

Can't we simply give this a private member called __is_join_view_iterator and check whether that member exists from a befriended class?

huixie90 added inline comments.Jan 30 2023, 2:55 PM
libcxx/include/__ranges/join_view.h
184

@ldionne
That was the first thing I tried.

https://godbolt.org/z/Ws3baE1E1

It did not work because, even though Derived does not have access Base::flag. the friend Checker can still access Derived::flag as the flag is part of the Base sub object.

today I realised that I can make the befriended thing a template and only friend the particular instantiation.
https://godbolt.org/z/771rjzvzq

what do you think?

huixie90 edited the summary of this revision. (Show Details)Feb 1 2023, 11:35 AM
ldionne added inline comments.Feb 2 2023, 12:21 PM
libcxx/include/__ranges/join_view.h
184

To be honest, I am not certain that all of these gymnastics are necessary. I don't see why someone would ever inherit from one of these iterators, and if they do, I think it may be reasonable for them to be broken. And if there's a good reason to do that, then we can change our detection of segmented iterators to account for that as a bug fix. So personally, I'd go for the simplest mechanism that doesn't handle derived types properly and I'd call it a day.

The other thing we could do BTW is mark the iterator class as final (which is non-conforming but not by much, and for an arguably good reason), and/or create a LWG issue (or write a paper?) asking for ranges iterators to be marked final. Ranges iterators are somewhat special because they are defined as nested classes, which is not super frequent and creates the ADL difficulties that you noted in the first place. As a result, I think it would make sense to consider this problem for all nested iterator types inside Ranges and I think a paper would probably make sense.

huixie90 updated this revision to Diff 494828.Feb 4 2023, 7:58 AM

make the iterator final

huixie90 updated this revision to Diff 494829.Feb 4 2023, 7:59 AM

remove unused code

ldionne accepted this revision.Feb 8 2023, 1:36 PM

This looks like a reasonable compromise to me. Let's cherry-pick.

libcxx/include/__ranges/join_view.h
185

Can you add a comment explaining what this final is?

This revision is now accepted and ready to land.Feb 8 2023, 1:36 PM