This is an archive of the discontinued LLVM Phabricator instance.

[libc++] Add the std::views::common range adaptor
ClosedPublic

Authored by ldionne on Sep 24 2021, 10:30 AM.

Details

Reviewers
Quuxplusone
Group Reviewers
Restricted Project
Commits
rG940755515da6: [libc++] Add the std::views::common range adaptor

Diff Detail

Event Timeline

ldionne requested review of this revision.Sep 24 2021, 10:30 AM
ldionne created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptSep 24 2021, 10:30 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript

LGTM mod comments, all of which are nits, I think.

libcxx/test/std/ranges/range.adaptors/range.common.view/adaptor.pass.cpp
33

It would be good to test a non-view type also (i.e. one where all_t<R> isn't R). Something like [UNTESTED]

std::vector<int> v = {1, 2, 3};
auto r = std::views::common(v);
ASSERT_SAME_TYPE(decltype(r), std::ranges::ref_view<std::vector<int>>);
89

Also

static_assert(!CanBePiped<std::vector<int>, decltype(std::views::common)>);

or perhaps replace line 88 with

static_assert( CanBePiped<int(&)[10], decltype(std::views::common)>);
static_assert(!CanBePiped<int(&&)[10], decltype(std::views::common)>);
static_assert(!CanBePiped<int, decltype(std::views::common)>);
94

Not only that, but std::addressof(std::views::common) == std::addressof(std::ranges::views::common).
I don't know if we really care about testing this; but if we do, then perhaps we should test all the members of namespace views, in one single test file, together.

libcxx/test/std/ranges/range.adaptors/range.common.view/types.h
112

If this noexcept is needed, something is wonky. Ditto on line 124.

116

For my own information: Are the multiple overloads actually needed? I do have some vague recollection that they might be, for some poison-pill-related reason, but if so, geez, that's awful. :P

jloser added a subscriber: jloser.Sep 24 2021, 3:18 PM
jloser added inline comments.
libcxx/test/std/ranges/range.adaptors/range.common.view/adaptor.nodiscard.verify.cpp
12 ↗(On Diff #374901)

Question: since this is a libc++ extension, should we move this file into libcxx/test/libcxx for example?

ldionne updated this revision to Diff 375322.Sep 27 2021, 10:12 AM
ldionne marked 5 inline comments as done.

Address review comments. Thanks!

libcxx/test/std/ranges/range.adaptors/range.common.view/adaptor.nodiscard.verify.cpp
12 ↗(On Diff #374901)

Yes, the convention would be to put those in libcxx/test/libcxx. However, I've been sort of on the fence about this recently, it feels easier and clearer to put those alongside the normal tests and just use REQUIRES: libc++ to express that it's a libc++ specific test. The benefits I see are that you don't have to search for tests in two directories, and also there's no risk of the folder hierarchies getting out of sync if they get moved around.

I'll move it to libcxx/test/libcxx if you request it, otherwise I'll leave as-is.

libcxx/test/std/ranges/range.adaptors/range.common.view/adaptor.pass.cpp
33

Good suggestion, done. I used <array> because it's constexpr friendly.

89

I'm curious to understand why int(&&)[10] can't be piped?

94

We're not supposed to be able to take the address of those so I think it's reasonable not to test for that.

libcxx/test/std/ranges/range.adaptors/range.common.view/types.h
116

Yes, they are necessary for the poison pill thing, and yes, it's awful.

jloser added inline comments.Sep 27 2021, 10:17 AM
libcxx/test/std/ranges/range.adaptors/range.common.view/adaptor.nodiscard.verify.cpp
12 ↗(On Diff #374901)

FWIW, I'm OK leaving it where it is now alongside the other tests. I prefer that, but will point out we have some inconsistency it seems. We can clean it up at some point in the future if desired (I'd be in favor of it).

ldionne accepted this revision as: Restricted Project.Sep 27 2021, 11:58 AM
This revision is now accepted and ready to land.Sep 27 2021, 11:58 AM
Mordante added inline comments.
libcxx/include/__ranges/common_view.h
112

Shouldn't there be tests to verify the noexcept status of the adaptor?

libcxx/test/std/ranges/range.adaptors/range.common.view/adaptor.nodiscard.verify.cpp
12 ↗(On Diff #374901)

But being a verify test already implies a libc++ test. I've seen those more often in the std directory.

ldionne updated this revision to Diff 375403.Sep 27 2021, 2:13 PM

Fix modules CI issue

libcxx/test/std/ranges/range.adaptors/range.common.view/adaptor.nodiscard.verify.cpp
12 ↗(On Diff #374901)

@ldionne:

I've been sort of on the fence about this recently, it feels easier and clearer to put those alongside the normal tests and just use REQUIRES: libc++ to express that it's a libc++ specific test

@Mordante:

But being a verify test already implies a libc++ test.

I think Louis's point makes sense; I'm fine with leaving .verify.cpp tests in the test/std/ directory, as long as the test runner — and all human contributors! — will understand that .verify.cpp implies "run only with Clang, and only with libc++."
I have one question about the proposed-new-status-quo, and two very minor items to put in the "against" column, just to show I've thought of them and rejected them:

  • Question: In the proposed-new-status-quo, since .verify.cpp implies "libc++ and Clang," isn't REQUIRES: libc++ redundant here? I think you should remove it.
  • Minor con: Contributors often add new tests by grabbing an existing test and modifying it. Putting .verify.cpp tests next to .pass.cpp tests might make it slightly more likely that a contributor will accidentally grab and modify the wrong kind of test. (But this point is pretty weak.)
  • Minor con: Each .verify.cpp test is kind of like a little TODO, because it identifies test coverage that is present for Clang but missing for other compilers. Each test/libcxx/ test is kind of like a little TODO, too, because it identifies test coverage for features that are in libc++ but lack standards-conformance for one reason or another. So putting all these little TODO items in one place might make it easier to see how big is the "backlog" or "gap" between libc++ and full conformance. (But find test/ -name *.verify.cpp is just as easy to type as find test/libcxx/, so this point is even weaker.)
libcxx/test/std/ranges/range.adaptors/range.common.view/adaptor.pass.cpp
61

Why introduce this typedef? Couldn't you just use NonCommonView throughout, below?

76–77

Just kvetching for the record: I see no benefit to this newfangled approach over the old-school no-Result-typedef approach of

auto result = partial(view);
ASSERT_SAME_TYPE(decltype(result), std::ranges::common_view<std::ranges::transform_view<SomeView, decltype(f)>>);
libcxx/test/std/ranges/range.adaptors/range.common.view/adaptor.pass.cpp
89

Assuming I'm correct that int(&&)[10] can't be piped :) my intuition is that rvalues of non-borrowed-range types can never be piped. int(&&)[10] is not an lvalue reference type, and int[10] is not a borrowed-range type; Q.E.D.

We aren't used to thinking about array rvalues in C++, but they're just like any other rvalue. See https://quuxplusone.github.io/blog/2021/08/07/p2266-field-test-results/#libreoffice-ostring for another example from like a month ago.

94

I agree; but I meant that right now you're just testing that views::x and ranges::views::x have the same type; you're not actually testing that they are two different names for the same object (which is what we want).
You can definitely pass std::views::common by reference to a function — that is a deliberate supported use-case — so you can get its address by using addressof on that reference. I don't know where we draw the line between "manipulating an object by reference such that you obtain a pointer to the object" (which is fine) and "taking the object's address" (which is allegedly forbidden). ;)
Anyway, minor point. I still think that if we're spending brain cells on this, we should do it for all the views, in one place, not scattered. And if we're not spending brain cells on it, then ship it. :)

Mordante added inline comments.Sep 28 2021, 10:34 AM
libcxx/test/std/ranges/range.adaptors/range.common.view/adaptor.nodiscard.verify.cpp
12 ↗(On Diff #374901)

Hmm I see my post was a bit terse. But I meant:

  • Keep the file at its current location.
  • Remove the REQUIRES: libc++
ldionne updated this revision to Diff 375939.Sep 29 2021, 10:06 AM
ldionne marked 3 inline comments as done.

Address review comments, in particular fix the confusion with .verify.cpp.

libcxx/test/std/ranges/range.adaptors/range.common.view/adaptor.nodiscard.verify.cpp
12 ↗(On Diff #374901)

Okay, reading this discussion made me change my mind, I guess. There are some misconceptions. verify.cpp tests are *not* libc++ specific in spirit. verify.cpp tests are simply a type of test supported by the testing format, and I don't think it makes sense to tie them to a specific implementation of the C++ stdlib.

Also, they are not Clang specific *in spirit*. It is true that we don't support them with any other compiler right now because we need a compiler that supports clang-verify, but in theory it would be conceivable to support verify.cpp tests for other compilers. There would also be issues with how to translate diagnostics and all, but my point is that in spirit there's nothing Clang or libc++ specific with those tests.

So what I'm going to do is move those libc++ specific tests to libcxx/test/libcxx, and also do a pass at our existing tests to move the libc++ specific ones to the right location.

libcxx/test/std/ranges/range.adaptors/range.common.view/adaptor.pass.cpp
61

Cause I wanted to capture the fact that it's just "some view" -- I didn't pick NonCommonView specifically, it could have been a CommonView too.

76–77

In this case you're right because Result = ..... is long so I put it on its own line, but in general it does reduce duplication in the tests and it can be easier to read. I'm not strongly attached to it, but I kind of liked it when (I think) @cjdb mentioned it to me, so I started adopting it. I'll keep doing that unless we come to an agreement that it's inferior.

94

I'll colocate those tests in an upcoming patch.

Mordante added inline comments.Sep 29 2021, 10:38 AM
libcxx/test/std/ranges/range.adaptors/range.common.view/adaptor.nodiscard.verify.cpp
12 ↗(On Diff #374901)

Thanks for the clarification and moving the appropriate tests.

This revision was automatically updated to reflect the committed changes.