Page MenuHomePhabricator

[libcxx][iterator] adds `std::ranges::distance`
Changes PlannedPublic

Authored by cjdb on Wed, May 19, 10:55 AM.

Details

Reviewers
ldionne
zoecarver
Mordante
Quuxplusone
Group Reviewers
Restricted Project
Summary

Implements part of P0896 'The One Ranges Proposal'.
Implements [range.iter.op.distance].

Depends on D102564 and D102434.

Diff Detail

Event Timeline

cjdb created this revision.Wed, May 19, 10:55 AM
cjdb requested review of this revision.Wed, May 19, 10:55 AM
Herald added a project: Restricted Project. · View Herald TranscriptWed, May 19, 10:55 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript
Quuxplusone added inline comments.Wed, May 19, 4:33 PM
libcxx/include/__iterator/distance.h
40–45

Please put lines 40-45 in an else block, so that we don't instantiate them unnecessarily in the case that the if block is taken.

48–55

I notice we're not doing the noexcept thing here. Is that because https://eel.is/c++draft/range.iter.op.distance#3 says merely "equivalent to" instead of the term of power "expression-equivalent to"?

libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/distance.verify.cpp
17

I don't think you're (that is, I don't think the programmer is) allowed to add your own types to namespace std::ranges.

39–46

We could do this in a .pass.cpp by SFINAE-testing the well-formedness of distance(r), instead of relying on the exact wording of the compiler error and then having to skip the test for non-Clang compilers.

cjdb added inline comments.Wed, May 19, 6:03 PM
libcxx/include/__iterator/distance.h
48–55

Yes. As it is, the noexcept specifiers would either be really difficult to read or would need their own special functions, neither of which I'm keen to do.

I've just noticed that having four overloads won't hurt readability like it did with ranges::advance, so I think I can get away with making ranges::distance noexcept without it being a colossal eyesore. (I might have fixed the problem with ranges::advance, so I'll need to go back and check soon.)

libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/distance.verify.cpp
17

I'm aware users aren't allowed to do this, but we're testing the standard library here. We need to ensure that ADL doesn't find something in the same namespace as the function, but there's nothing to test with (no range adaptors have been merged with main yet).

39–46

Something like this?

template<class T>
constexpr bool is_adl_friendly = requires(T t) { distance(t); };

static_assert(!is_adl_friendly<std::ranges::forward_iterator>);
static_assert(!is_adl_friendly<std::ranges::some_range>);

SGTM. no real comments from me, I'll have another look after you addressed Arthur's review comments.

libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/distance.verify.cpp
17

Would it make sense to add a TODO and improve this test after we have adaptors?

ldionne requested changes to this revision.Tue, May 25, 1:04 PM
ldionne added inline comments.
libcxx/include/__iterator/distance.h
35

Drop [[nodiscard]]

libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/distance.pass.cpp
13

Please split into two test files, one for each overload.

45

Can we avoid using a global range here (and below) and instead have a local variable? It's a tiny difference but it helps local reasoning.

libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/distance.verify.cpp
17

@cjdb Please add a TODO like you've done in other patches, we'll go back and fix it as soon as we check-in an adaptor.

libcxx/test/support/test_iterators.h
877

Drop [[nodiscard]] from the tests (here and elsewhere), except for really vexing cases as we've discussed (but I don't think there's any).

This revision now requires changes to proceed.Tue, May 25, 1:04 PM
cjdb planned changes to this revision.Wed, Jun 2, 10:34 AM

Changes to be applied in the next day or so.

libcxx/include/__iterator/distance.h
35

After much deliberation on this, I think it's worth considering that we keep [[nodiscard]] on anything that consumes a proper input_iterator or output_iterator. Two reasons:

  • they could be move-only (thus the result is lost forever)