Skip to content

Commit

Permalink
Add unwrapping to move_sentinel (#3098)
Browse files Browse the repository at this point in the history
Co-authored-by: Nicole Mazzuca <[email protected]>
Co-authored-by: Stephan T. Lavavej <[email protected]>
  • Loading branch information
3 people authored Sep 13, 2022
1 parent 6c0c9a9 commit ac129e5
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 57 deletions.
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>>();
#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

0 comments on commit ac129e5

Please sign in to comment.