public inbox for libstdc++-cvs@sourceware.org help / color / mirror / Atom feed
From: Jonathan Wakely <redi@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r10-9569] libstdc++: Fix constraints for drop_view::begin() const [LWG 3482] Date: Mon, 29 Mar 2021 20:01:17 +0000 (GMT) [thread overview] Message-ID: <20210329200117.76C753850428@sourceware.org> (raw) https://gcc.gnu.org/g:9b04d5aaef683293d6cbdc7d0bcf1d117e27355a commit r10-9569-g9b04d5aaef683293d6cbdc7d0bcf1d117e27355a Author: Jonathan Wakely <jwakely@redhat.com> Date: Mon Sep 21 23:43:25 2020 +0100 libstdc++: Fix constraints for drop_view::begin() const [LWG 3482] libstdc++-v3/ChangeLog: * include/std/ranges (drop_view::begin()): Adjust constraints to match the correct condition for O(1) ranges::next (LWG 3482). * testsuite/std/ranges/adaptors/drop.cc: Check that iterator is cached for non-sized_range. (cherry picked from commit aecea4158f4e547af349657a3d16cb031a30ec3b) Diff: --- libstdc++-v3/include/std/ranges | 17 ++- libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc | 128 +++++++++++++++++++-- 2 files changed, 131 insertions(+), 14 deletions(-) diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index ea271150bd7..8d3b662f928 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -2264,7 +2264,10 @@ namespace views _Vp _M_base = _Vp(); range_difference_t<_Vp> _M_count = 0; - static constexpr bool _S_needs_cached_begin = !random_access_range<_Vp>; + // ranges::next(begin(base), count, end(base)) is O(1) if _Vp satisfies + // both random_access_range and sized_range. Otherwise, cache its result. + static constexpr bool _S_needs_cached_begin + = !(random_access_range<const _Vp> && sized_range<const _Vp>); [[no_unique_address]] __detail::__maybe_present_t<_S_needs_cached_begin, __detail::_CachedPosition<_Vp>> @@ -2286,9 +2289,12 @@ namespace views base() && { return std::move(_M_base); } + // This overload is disabled for simple views with constant-time begin(). constexpr auto - begin() requires (!(__detail::__simple_view<_Vp> - && random_access_range<_Vp>)) + begin() + requires (!(__detail::__simple_view<_Vp> + && random_access_range<const _Vp> + && sized_range<const _Vp>)) { if constexpr (_S_needs_cached_begin) if (_M_cached_begin._M_has_value()) @@ -2301,8 +2307,11 @@ namespace views return __it; } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3482. drop_view's const begin should additionally require sized_range constexpr auto - begin() const requires random_access_range<const _Vp> + begin() const + requires random_access_range<const _Vp> && sized_range<const _Vp> { return ranges::next(ranges::begin(_M_base), _M_count, ranges::end(_M_base)); diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc index 3c82caea772..5fe94b67507 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc @@ -26,6 +26,7 @@ using __gnu_test::test_range; using __gnu_test::forward_iterator_wrapper; using __gnu_test::bidirectional_iterator_wrapper; +using __gnu_test::random_access_iterator_wrapper; namespace ranges = std::ranges; namespace views = ranges::views; @@ -123,8 +124,52 @@ struct test_wrapper : forward_iterator_wrapper<T> forward_iterator_wrapper<T>::operator++(); return *this; } +}; - test_wrapper +void +test07() +{ + int x[] = {1,2,3,4,5}; + test_range<int, test_wrapper> rx(x); + auto v = rx | views::drop(3); + VERIFY( test_wrapper<int>::increment_count == 0 ); + (void) v.begin(); + VERIFY( test_wrapper<int>::increment_count == 3 ); + (void) v.begin(); + VERIFY( test_wrapper<int>::increment_count == 3 ); + VERIFY( ranges::equal(v, (int[]){4,5}) ); + VERIFY( test_wrapper<int>::increment_count == 5 ); + VERIFY( ranges::equal(v, (int[]){4,5}) ); + VERIFY( test_wrapper<int>::increment_count == 7 ); +} + +template<typename T> +struct ra_test_wrapper : random_access_iterator_wrapper<T> +{ + static inline int increment_count = 0; + + using random_access_iterator_wrapper<T>::random_access_iterator_wrapper; + + ra_test_wrapper() : random_access_iterator_wrapper<T>() + { } + + ra_test_wrapper + operator++(int) + { + auto tmp = *this; + ++*this; + return tmp; + } + + ra_test_wrapper& + operator++() + { + ++increment_count; + random_access_iterator_wrapper<T>::operator++(); + return *this; + } + + ra_test_wrapper operator--(int) { auto tmp = *this; @@ -132,23 +177,85 @@ struct test_wrapper : forward_iterator_wrapper<T> return tmp; } - test_wrapper& + ra_test_wrapper& operator--() { - forward_iterator_wrapper<T>::operator--(); + random_access_iterator_wrapper<T>::operator--(); + return *this; + } + + ra_test_wrapper& + operator+=(std::ptrdiff_t n) + { + random_access_iterator_wrapper<T>::operator+=(n); return *this; } + + ra_test_wrapper& + operator-=(std::ptrdiff_t n) + { return *this += -n; } + + ra_test_wrapper + operator+(std::ptrdiff_t n) const + { + auto tmp = *this; + return tmp += n; + } + + ra_test_wrapper + operator-(std::ptrdiff_t n) const + { + auto tmp = *this; + return tmp -= n; + } + + std::ptrdiff_t + operator-(const ra_test_wrapper& it) const + { + return static_cast<const random_access_iterator_wrapper<T>&>(*this) - it; + } + + friend ra_test_wrapper + operator+(std::ptrdiff_t n, const ra_test_wrapper& it) + { return it + n; } }; void -test07() +test08() { - int x[] = {1,2,3,4,5}; - test_range<int, test_wrapper> rx(x); - auto v = rx | views::drop(3); - VERIFY( ranges::equal(v, (int[]){4,5}) ); - VERIFY( ranges::equal(v, (int[]){4,5}) ); - VERIFY( test_wrapper<int>::increment_count == 7 ); + // LWG 3482 - drop_view's const begin should additionally require sized_range + + short a[10]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + test_range<short, ra_test_wrapper> ra(a); + static_assert( ranges::random_access_range<decltype(ra)> ); + ranges::subrange nonsized = {ra.begin(), std::unreachable_sentinel}; + using Nonsized = decltype(nonsized); + static_assert( ranges::random_access_range<Nonsized> ); + static_assert( ! ranges::sized_range<Nonsized> ); + auto v1 = nonsized | views::drop(5); + VERIFY( ra_test_wrapper<short>::increment_count == 0 ); + auto b1 = v1.begin(); + VERIFY( ra_test_wrapper<short>::increment_count == 5 ); + VERIFY( v1.begin() == b1 ); + VERIFY( ra_test_wrapper<short>::increment_count == 5 ); + VERIFY( *b1 == 5 ); + VERIFY( *v1.begin() == 5 ); + VERIFY( ra_test_wrapper<short>::increment_count == 5 ); + + long b[10]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + test_range<long, ra_test_wrapper> rb(b); + ranges::subrange sized = {rb.begin(), rb.begin()+6}; + using Sized = decltype(sized); + static_assert( ranges::random_access_range<Sized> ); + static_assert( ranges::sized_range<Sized> ); + auto v2 = sized | views::drop(6); + auto b2 = v2.begin(); + VERIFY( ra_test_wrapper<long>::increment_count == 0 ); + VERIFY( v2.begin() == b2 ); + VERIFY( ra_test_wrapper<long>::increment_count == 0 ); + VERIFY( *b2 == 6 ); + VERIFY( *v2.begin() == 6 ); + VERIFY( ra_test_wrapper<long>::increment_count == 0 ); } int @@ -161,4 +268,5 @@ main() test05(); test06(); test07(); + test08(); }
reply other threads:[~2021-03-29 20:01 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20210329200117.76C753850428@sourceware.org \ --to=redi@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ --cc=libstdc++-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).