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

Add unwrapping to move_sentinel #3098

Merged
merged 4 commits into from
Sep 13, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
17 changes: 17 additions & 0 deletions stl/inc/iterator
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,23 @@ public:
return _Last;
}

using _Prevent_inheriting_unwrap = move_sentinel;

// clang-format off
_NODISCARD constexpr move_sentinel<_Unwrapped_t<const _Se&>> _Unwrapped() const&
noexcept(noexcept(move_sentinel<_Unwrapped_t<const _Se&>>{_Last._Unwrapped()}))
requires _RANGES _Weakly_unwrappable_sentinel<_Se> {
// clang-format on
return move_sentinel<_Unwrapped_t<const _Se&>>{_Last._Unwrapped()};
}
// clang-format off
_NODISCARD constexpr move_sentinel<_Unwrapped_t<_Se>> _Unwrapped() &&
noexcept(noexcept(move_sentinel<_Unwrapped_t<_Se>>{_STD move(_Last)._Unwrapped()}))
requires _RANGES _Weakly_unwrappable_sentinel<_Se> {
// clang-format on
return move_sentinel<_Unwrapped_t<_Se>>{_STD move(_Last)._Unwrapped()};
}

private:
_Se _Last{};
};
Expand Down
27 changes: 22 additions & 5 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -1846,13 +1846,30 @@ namespace ranges {
template <range _Rng>
using sentinel_t = decltype(_RANGES end(_STD declval<_Rng&>()));

template <class _Wrapped>
concept _Weakly_unwrappable =
same_as<typename remove_cvref_t<_Wrapped>::_Prevent_inheriting_unwrap, remove_cvref_t<_Wrapped>> //
&& requires(_Wrapped&& _Wr) {
_STD forward<_Wrapped>(_Wr)._Unwrapped();
};

// clang-format off
template <class _Sent>
concept _Weakly_unwrappable_sentinel = _Weakly_unwrappable<const remove_reference_t<_Sent>&>;
// clang-format on

template <class _Iter>
concept _Weakly_unwrappable_iterator = //
_Weakly_unwrappable<_Iter> //
&& requires(_Iter&& _It, remove_cvref_t<_Iter>& _MutIt) {
_MutIt._Seek_to(_STD forward<_Iter>(_It)._Unwrapped());
};

template <class _Sent, class _Iter>
concept _Unwrappable_sentinel_for = //
same_as<typename remove_cvref_t<_Sent>::_Prevent_inheriting_unwrap, remove_cvref_t<_Sent>> //
&& same_as<typename remove_cvref_t<_Iter>::_Prevent_inheriting_unwrap, remove_cvref_t<_Iter>> //
&& requires(_Iter&& _It, remove_cvref_t<_Iter>& _MutIt, const remove_reference_t<_Sent>& _Se) {
_STD forward<_Iter>(_It)._Unwrapped();
_MutIt._Seek_to(_STD forward<_Iter>(_It)._Unwrapped());
_Weakly_unwrappable_sentinel<_Sent> //
&& _Weakly_unwrappable_iterator<_Iter> //
&& requires(_Iter&& _It, const remove_reference_t<_Sent>& _Se) {
{ _Se._Unwrapped() } -> sentinel_for<decltype(_STD forward<_Iter>(_It)._Unwrapped())>;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <map>
#include <set>
#include <string>
#include <string_view>
#include <unordered_map>
#include <unordered_set>
#include <vector>
Expand Down Expand Up @@ -39,8 +40,11 @@ void test_algorithms(Rng& rng) {
}
}

template <class It, class Se>
void test_unwrappable_pair() {
template <class Rng>
void test_unwrappable_range() {
using It = ranges::iterator_t<Rng>;
using Se = ranges::sentinel_t<Rng>;

constexpr bool is_const_unwrappable = requires(const It& ci) {
ci._Unwrapped();
};
Expand Down Expand Up @@ -70,12 +74,15 @@ void test_unwrappable_pair() {
noexcept(ranges::_Unwrap_sent<It>(declval<const Se&>())) == noexcept(declval<const Se&>()._Unwrapped()));

// instantiate without calling
void (*p)(ranges::subrange<It, Se>&) = test_algorithms<ranges::subrange<It, Se>>;
void (*p)(Rng&) = test_algorithms<Rng>;
(void) p;
}

template <class It, class Se>
void test_not_unwrappable_pair() {
template <class Rng>
void test_not_unwrappable_range() {
using It = ranges::iterator_t<Rng>;
using Se = ranges::sentinel_t<Rng>;

STATIC_ASSERT(!ranges::_Unwrappable_sentinel_for<Se, It>);
STATIC_ASSERT(same_as<ranges::_Unwrap_iter_t<It, Se>, It>);
STATIC_ASSERT(same_as<ranges::_Unwrap_iter_t<const It&, Se>, It>);
Expand All @@ -90,14 +97,14 @@ void test_not_unwrappable_pair() {
STATIC_ASSERT(noexcept(ranges::_Unwrap_sent<It>(declval<const Se&>())));

// instantiate without calling
void (*p)(ranges::subrange<It, Se>&) = test_algorithms<ranges::subrange<It, Se>>;
void (*p)(Rng&) = test_algorithms<Rng>;
(void) p;
}

template <class Rng>
void test_classic_range() {
test_unwrappable_pair<ranges::iterator_t<Rng>, ranges::sentinel_t<Rng>>();
test_unwrappable_pair<ranges::iterator_t<const Rng>, ranges::sentinel_t<const Rng>>();
test_unwrappable_range<Rng>();
test_unwrappable_range<const Rng>();
}
void test_classic_ranges() {
test_classic_range<string>();
Expand All @@ -113,6 +120,10 @@ void test_classic_ranges() {
test_classic_range<unordered_map<int, int>>();
test_classic_range<vector<int>>();
test_classic_range<filesystem::path>();

#if _HAS_CXX23
test_classic_range<ranges::as_rvalue_view<string_view>>();
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
#endif
}

struct Nontrivial {
Expand All @@ -130,23 +141,45 @@ struct Nontrivial {
bool operator==(const Nontrivial&) const noexcept = default;
};

template <class Iter, class Sent>
void test_unwrappable_views() {
using R = ranges::subrange<Iter, Sent>;

test_unwrappable_range<R>();

#if _HAS_CXX23
test_unwrappable_range<ranges::as_rvalue_view<R>>();
#endif
}

template <class Iter, class Sent>
void test_not_unwrappable_views() {
using R = ranges::subrange<Iter, Sent>;

test_not_unwrappable_range<R>();

#if _HAS_CXX23
test_not_unwrappable_range<ranges::as_rvalue_view<R>>();
#endif
}

void test_both_unwrappable() {
using test::contiguous, test::random, test::bidi, test::fwd, test::input;

using sent_int = test::sentinel<int>;
using sent_nt = test::sentinel<Nontrivial>;

test_unwrappable_pair<test::iterator<contiguous, int>, sent_int>();
test_unwrappable_pair<test::iterator<random, int>, sent_int>();
test_unwrappable_pair<test::iterator<bidi, int>, sent_int>();
test_unwrappable_pair<test::iterator<fwd, int>, sent_int>();
test_unwrappable_pair<test::iterator<input, int>, sent_int>();

test_unwrappable_pair<test::iterator<contiguous, Nontrivial>, sent_nt>();
test_unwrappable_pair<test::iterator<random, Nontrivial>, sent_nt>();
test_unwrappable_pair<test::iterator<bidi, Nontrivial>, sent_nt>();
test_unwrappable_pair<test::iterator<fwd, Nontrivial>, sent_nt>();
test_unwrappable_pair<test::iterator<input, Nontrivial>, sent_nt>();
test_unwrappable_views<test::iterator<contiguous, int>, sent_int>();
test_unwrappable_views<test::iterator<random, int>, sent_int>();
test_unwrappable_views<test::iterator<bidi, int>, sent_int>();
test_unwrappable_views<test::iterator<fwd, int>, sent_int>();
test_unwrappable_views<test::iterator<input, int>, sent_int>();

test_unwrappable_views<test::iterator<contiguous, Nontrivial>, sent_nt>();
test_unwrappable_views<test::iterator<random, Nontrivial>, sent_nt>();
test_unwrappable_views<test::iterator<bidi, Nontrivial>, sent_nt>();
test_unwrappable_views<test::iterator<fwd, Nontrivial>, sent_nt>();
test_unwrappable_views<test::iterator<input, Nontrivial>, sent_nt>();
}

void test_iter_unwrappable() {
Expand All @@ -155,17 +188,17 @@ void test_iter_unwrappable() {
using sent_int = test::sentinel<int, test::WrappedState::ignorant>;
using sent_nt = test::sentinel<Nontrivial, test::WrappedState::ignorant>;

test_not_unwrappable_pair<test::iterator<contiguous, int>, sent_int>();
test_not_unwrappable_pair<test::iterator<random, int>, sent_int>();
test_not_unwrappable_pair<test::iterator<bidi, int>, sent_int>();
test_not_unwrappable_pair<test::iterator<fwd, int>, sent_int>();
test_not_unwrappable_pair<test::iterator<input, int>, sent_int>();

test_not_unwrappable_pair<test::iterator<contiguous, Nontrivial>, sent_nt>();
test_not_unwrappable_pair<test::iterator<random, Nontrivial>, sent_nt>();
test_not_unwrappable_pair<test::iterator<bidi, Nontrivial>, sent_nt>();
test_not_unwrappable_pair<test::iterator<fwd, Nontrivial>, sent_nt>();
test_not_unwrappable_pair<test::iterator<input, Nontrivial>, sent_nt>();
test_not_unwrappable_views<test::iterator<contiguous, int>, sent_int>();
test_not_unwrappable_views<test::iterator<random, int>, sent_int>();
test_not_unwrappable_views<test::iterator<bidi, int>, sent_int>();
test_not_unwrappable_views<test::iterator<fwd, int>, sent_int>();
test_not_unwrappable_views<test::iterator<input, int>, sent_int>();

test_not_unwrappable_views<test::iterator<contiguous, Nontrivial>, sent_nt>();
test_not_unwrappable_views<test::iterator<random, Nontrivial>, sent_nt>();
test_not_unwrappable_views<test::iterator<bidi, Nontrivial>, sent_nt>();
test_not_unwrappable_views<test::iterator<fwd, Nontrivial>, sent_nt>();
test_not_unwrappable_views<test::iterator<input, Nontrivial>, sent_nt>();
}

void test_sent_unwrappable() {
Expand All @@ -174,17 +207,17 @@ void test_sent_unwrappable() {
using sent_int = test::sentinel<int>;
using sent_nt = test::sentinel<Nontrivial>;

test_not_unwrappable_pair<test::iterator<contiguous, int>::unwrapping_ignorant, sent_int>();
test_not_unwrappable_pair<test::iterator<random, int>::unwrapping_ignorant, sent_int>();
test_not_unwrappable_pair<test::iterator<bidi, int>::unwrapping_ignorant, sent_int>();
test_not_unwrappable_pair<test::iterator<fwd, int>::unwrapping_ignorant, sent_int>();
test_not_unwrappable_pair<test::iterator<input, int>::unwrapping_ignorant, sent_int>();

test_not_unwrappable_pair<test::iterator<contiguous, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_pair<test::iterator<random, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_pair<test::iterator<bidi, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_pair<test::iterator<fwd, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_pair<test::iterator<input, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_views<test::iterator<contiguous, int>::unwrapping_ignorant, sent_int>();
test_not_unwrappable_views<test::iterator<random, int>::unwrapping_ignorant, sent_int>();
test_not_unwrappable_views<test::iterator<bidi, int>::unwrapping_ignorant, sent_int>();
test_not_unwrappable_views<test::iterator<fwd, int>::unwrapping_ignorant, sent_int>();
test_not_unwrappable_views<test::iterator<input, int>::unwrapping_ignorant, sent_int>();

test_not_unwrappable_views<test::iterator<contiguous, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_views<test::iterator<random, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_views<test::iterator<bidi, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_views<test::iterator<fwd, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_views<test::iterator<input, Nontrivial>::unwrapping_ignorant, sent_nt>();
}

void test_neither_unwrappable() {
Expand All @@ -193,17 +226,17 @@ void test_neither_unwrappable() {
using sent_int = test::sentinel<int, test::WrappedState::ignorant>;
using sent_nt = test::sentinel<Nontrivial, test::WrappedState::ignorant>;

test_not_unwrappable_pair<test::iterator<contiguous, int>::unwrapping_ignorant, sent_int>();
test_not_unwrappable_pair<test::iterator<random, int>::unwrapping_ignorant, sent_int>();
test_not_unwrappable_pair<test::iterator<bidi, int>::unwrapping_ignorant, sent_int>();
test_not_unwrappable_pair<test::iterator<fwd, int>::unwrapping_ignorant, sent_int>();
test_not_unwrappable_pair<test::iterator<input, int>::unwrapping_ignorant, sent_int>();

test_not_unwrappable_pair<test::iterator<contiguous, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_pair<test::iterator<random, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_pair<test::iterator<bidi, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_pair<test::iterator<fwd, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_pair<test::iterator<input, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_views<test::iterator<contiguous, int>::unwrapping_ignorant, sent_int>();
test_not_unwrappable_views<test::iterator<random, int>::unwrapping_ignorant, sent_int>();
test_not_unwrappable_views<test::iterator<bidi, int>::unwrapping_ignorant, sent_int>();
test_not_unwrappable_views<test::iterator<fwd, int>::unwrapping_ignorant, sent_int>();
test_not_unwrappable_views<test::iterator<input, int>::unwrapping_ignorant, sent_int>();

test_not_unwrappable_views<test::iterator<contiguous, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_views<test::iterator<random, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_views<test::iterator<bidi, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_views<test::iterator<fwd, Nontrivial>::unwrapping_ignorant, sent_nt>();
test_not_unwrappable_views<test::iterator<input, Nontrivial>::unwrapping_ignorant, sent_nt>();
}

int main() {} // COMPILE-ONLY