From patchwork Fri Oct 4 02:08:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 1992575 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=UyCXDQge; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XKX6Y1X75z1xsn for ; Fri, 4 Oct 2024 12:09:25 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D95AF384642B for ; Fri, 4 Oct 2024 02:09:22 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 12A61385DDEC for ; Fri, 4 Oct 2024 02:08:51 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 12A61385DDEC Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 12A61385DDEC Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1728007733; cv=none; b=RZKtIzVO/IbXBau4AjjjI4i56f7sY8pDBIQ77a9wYYYItFdGKgWRTgilnA0RC0q8HrJsZvEAXt/y/y2hgWfEsOq0B9G46lZkPEJtHHSlEBrhf28L2UPEs6AhEFujLvo04PJsWrKNmFHtQNW72mJRrn58TwrfKm6/+/YTXMLSCnk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1728007733; c=relaxed/simple; bh=idd1kT4InEH2xGhMWeHTRox8oracAghbXomteE+ePQs=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=HH1fiIByTaxU5Om8AQldCBTyTthfOWcIfm9ihvVw01ruDdhdGqxmQZb6CfWWN2suF+GJQZkk+jsyWxleyJYi+pqI0x43JchkwFdFNyEJmmBVCZoJMWjB64IitWz8kAYZJx7Db5S2W0M6jBg0N0szFv+IfK2RWgOVexFFfmLvhwA= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1728007730; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=v2KB5H+YwMBrDs56DGNu2C8vxnZfnvPqtvVIyNftdGI=; b=UyCXDQge7UG6OU2wrUt8gEmTtGz++XNiEoU6mFE9uPdmc9gY+S1KzOyJbJgd8bieHyMJHf hriAjE5QYlIxJvTcn2fBeVkAlJ+KttZORKRAnOuSmj6m0sFVKn9/NL1xMYttkqMB0aKFKm VytWcdqX/kOYwyBIDBmCf72AbEl33qY= Received: from mail-qv1-f71.google.com (mail-qv1-f71.google.com [209.85.219.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-668-gOcmjtisPmWpRSRgb5lirg-1; Thu, 03 Oct 2024 22:08:49 -0400 X-MC-Unique: gOcmjtisPmWpRSRgb5lirg-1 Received: by mail-qv1-f71.google.com with SMTP id 6a1803df08f44-6cb2847dd35so4174706d6.3 for ; Thu, 03 Oct 2024 19:08:49 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728007728; x=1728612528; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=v2KB5H+YwMBrDs56DGNu2C8vxnZfnvPqtvVIyNftdGI=; b=l7jbft8ZlBGaE0VnqLvjvLewk/1FOc97DPVdN9JbZGlQC3xaPxHfyqPDsxODB4h1Tn 3p5Bh/tunG2KA5Ng9pqy5vUPQ+Fqbz5sv9vUJSpoQOlzN0bvteXbEl0VW8KCssV+ovzH cxNWXFVZd3QNHSiFbzfqyhKrFh8dCH0RvteGIpLltDgip0PqRJmC24+PGUPEn96MuBwQ xRteedD7y6kk7PORgEac7qrmc3OwOxKJaVa8v4lSDdm0pbloQ5eZ89WfAZiJLnvTjeyy j6SCjrls3q1HSAlIvnta/a/WyOFt7v+zHQ6Kjd4AdZ7tkkbTqL8q8LsheHYwmI+xYEaD Eljg== X-Gm-Message-State: AOJu0YzmCoHkgJ22lk81FFuMWiTIfnQAi2RiIYNK/+z0hAWHtzE4bxdf jWKph+5IjvsKqMsyMVKzWSu8RQEthDvxUgTlPMju7kO+zH0r3/xRQwE41OX6BHAmbj300QqpXKd VGz1nWl9JlV1YIQO4eSMc38LavXI0srqdgxqJLrYU3pra35N3bMs3+6070asCBripMkhPHkN9Rz H5C88H6uNP2mGx0yNsl9i4CWlFDh232LXYxXtm X-Received: by 2002:a05:622a:2c44:b0:45d:9dc5:d1ac with SMTP id d75a77b69052e-45d9dc5e422mr3361511cf.10.1728007727705; Thu, 03 Oct 2024 19:08:47 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHiOI1VOn9auwaDPY038Pgy2reY7maba4aGzZOj4tQT3qYI5brRNvasOTYXqG0FQMpBU2rfkw== X-Received: by 2002:a05:622a:2c44:b0:45d:9dc5:d1ac with SMTP id d75a77b69052e-45d9dc5e422mr3361331cf.10.1728007727154; Thu, 03 Oct 2024 19:08:47 -0700 (PDT) Received: from localhost.localdomain (ool-18bb2a2e.dyn.optonline.net. [24.187.42.46]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-45d92de0123sm10515571cf.8.2024.10.03.19.08.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Oct 2024 19:08:46 -0700 (PDT) From: Patrick Palka To: gcc-patches@gcc.gnu.org Cc: libstdc++@gcc.gnu.org, Patrick Palka Subject: [PATCH] libstdc++/ranges: Implement various small LWG issues Date: Thu, 3 Oct 2024 22:08:44 -0400 Message-ID: <20241004020844.116894-1-ppalka@redhat.com> X-Mailer: git-send-email 2.47.0.rc1 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-13.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org Tested on x86_64-pc-linux-gnu, does this look OK for trunk/14 and perhaps 13? -- >8 -- This implements the following small LWG issues: 3848. adjacent_view, adjacent_transform_view and slide_view missing base accessor 3851. chunk_view::inner-iterator missing custom iter_move and iter_swap 3947. Unexpected constraints on adjacent_transform_view::base() 4001. iota_view should provide empty 4012. common_view::begin/end are missing the simple-view check 4013. lazy_split_view::outer-iterator::value_type should not provide default constructor 4035. single_view should provide empty 4053. Unary call to std::views::repeat does not decay the argument 4054. Repeating a repeat_view should repeat the view libstdc++-v3/ChangeLog: * include/std/ranges (single_view::empty): Define as per LWG 4035. (iota_view::empty): Define as per LWG 4001. (lazy_split_view::_OuterIter::value_type): Remove default constructor and make other constructor private as per LWG 4013. (common_view::begin): Disable non-const overload for simple views as per LWG 4012. (common_view::end): Likewise. (adjacent_view::base): Define as per LWG 3848. (adjacent_transform_view::base): Likewise. (chunk_view::_InnerIter::iter_move): Define as per LWG 3851. (chunk_view::_InnerIter::itep_swap): Likewise. (slide_view::base): Define as per LWG 3848. (repeat_view): Adjust deduction guide as per LWG 4053. (_Repeat::operator()): Adjust single-parameter overload as per LWG 4054. * testsuite/std/ranges/adaptors/adjacent/1.cc: Verify existence of base member function. * testsuite/std/ranges/adaptors/adjacent_transform/1.cc: Likewise. * testsuite/std/ranges/adaptors/chunk/1.cc: Test LWG 3851 example. * testsuite/std/ranges/adaptors/slide/1.cc: Verify existence of base member function. * testsuite/std/ranges/iota/iota_view.cc: Test LWG 4001 example. * testsuite/std/ranges/repeat/1.cc: Test LWG 4053/4054 examples. --- libstdc++-v3/include/std/ranges | 84 +++++++++++++++++-- .../std/ranges/adaptors/adjacent/1.cc | 3 + .../ranges/adaptors/adjacent_transform/1.cc | 3 + .../testsuite/std/ranges/adaptors/chunk/1.cc | 15 ++++ .../testsuite/std/ranges/adaptors/slide/1.cc | 3 + .../testsuite/std/ranges/iota/iota_view.cc | 12 +++ libstdc++-v3/testsuite/std/ranges/repeat/1.cc | 23 +++++ 7 files changed, 135 insertions(+), 8 deletions(-) diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 30f45e0a750..6e6e3b97d82 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -335,6 +335,12 @@ namespace ranges end() const noexcept { return data() + 1; } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4035. single_view should provide empty + static constexpr bool + empty() noexcept + { return false; } + static constexpr size_t size() noexcept { return 1; } @@ -695,6 +701,12 @@ namespace ranges end() const requires same_as<_Winc, _Bound> { return _Iterator{_M_bound}; } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4001. iota_view should provide empty + constexpr bool + empty() const + { return _M_value == _M_bound; } + constexpr auto size() const requires (same_as<_Winc, _Bound> && __detail::__advanceable<_Winc>) @@ -3349,14 +3361,17 @@ namespace views::__adaptor private: _OuterIter _M_i = _OuterIter(); - public: - value_type() = default; - + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4013. lazy_split_view::outer-iterator::value_type should not + // provide default constructor constexpr explicit value_type(_OuterIter __i) : _M_i(std::move(__i)) { } + friend _OuterIter; + + public: constexpr _InnerIter<_Const> begin() const { return _InnerIter<_Const>{_M_i}; } @@ -3948,8 +3963,10 @@ namespace views::__adaptor base() && { return std::move(_M_base); } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4012. common_view::begin/end are missing the simple-view check constexpr auto - begin() + begin() requires (!__detail::__simple_view<_Vp>) { if constexpr (random_access_range<_Vp> && sized_range<_Vp>) return ranges::begin(_M_base); @@ -3969,7 +3986,7 @@ namespace views::__adaptor } constexpr auto - end() + end() requires (!__detail::__simple_view<_Vp>) { if constexpr (random_access_range<_Vp> && sized_range<_Vp>) return ranges::begin(_M_base) + ranges::size(_M_base); @@ -5316,6 +5333,16 @@ namespace views::__adaptor : _M_base(std::move(__base)) { } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3848. adjacent_view, adjacent_transform_view and slide_view missing base accessor + constexpr _Vp + base() const & requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + constexpr auto begin() requires (!__detail::__simple_view<_Vp>) { return _Iterator(ranges::begin(_M_base), ranges::end(_M_base)); } @@ -5709,6 +5736,17 @@ namespace views::__adaptor : _M_fun(std::move(__fun)), _M_inner(std::move(__base)) { } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3848. adjacent_view, adjacent_transform_view and slide_view missing base accessor + // 3947. Unexpected constraints on adjacent_transform_view::base() + constexpr _Vp + base() const & requires copy_constructible<_Vp> + { return _M_inner.base(); } + + constexpr _Vp + base() && + { return std::move(_M_inner.base()); } + constexpr auto begin() { return _Iterator(*this, _M_inner.begin()); } @@ -6236,6 +6274,20 @@ namespace views::__adaptor operator-(const _InnerIter& __x, default_sentinel_t __y) requires sized_sentinel_for, iterator_t<_Vp>> { return -(__y - __x); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3851. chunk_view::inner-iterator missing custom iter_move and iter_swap + friend constexpr range_rvalue_reference_t<_Vp> + iter_move(const _InnerIter& __i) + noexcept(noexcept(ranges::iter_move(*__i._M_parent->_M_current))) + { return ranges::iter_move(*__i._M_parent->_M_current); } + + friend constexpr void + iter_swap(const _InnerIter& __x, const _InnerIter& __y) + noexcept(noexcept(ranges::iter_swap(*__x._M_parent->_M_current, + *__x._M_parent->_M_current))) + requires indirectly_swappable> + { return ranges::iter_swap(*__x._M_parent->_M_current, *__y._M_parent->_M_current); } }; template @@ -6577,6 +6629,16 @@ namespace views::__adaptor : _M_base(std::move(__base)), _M_n(__n) { __glibcxx_assert(__n > 0); } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3848. adjacent_view, adjacent_transform_view and slide_view missing base accessor + constexpr _Vp + base() const & requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + constexpr auto begin() requires (!(__detail::__simple_view<_Vp> && __detail::__slide_caches_nothing)) @@ -7692,8 +7754,10 @@ namespace views::__adaptor { return __detail::__to_unsigned_like(_M_bound); } }; - template - repeat_view(_Tp, _Bound) -> repeat_view<_Tp, _Bound>; + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4053. Unary call to std::views::repeat does not decay the argument + template + repeat_view(_Tp, _Bound = _Bound()) -> repeat_view<_Tp, _Bound>; template requires is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> @@ -7840,7 +7904,11 @@ namespace views::__adaptor requires __detail::__can_repeat_view<_Tp> constexpr auto operator() [[nodiscard]] (_Tp&& __value) const - { return repeat_view(std::forward<_Tp>(__value)); } + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4054. Repeating a repeat_view should repeat the view + return repeat_view>(std::forward<_Tp>(__value)); + } template requires __detail::__can_bounded_repeat_view<_Tp, _Bound> diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc index b83743a745c..085cd4a8c54 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc @@ -47,6 +47,9 @@ test01() VERIFY( &std::get<2>(v3[i]) == &y[i] + 2 ); } + // LWG 3848 - adjacent_view etc missing base accessor + v3.base(); + const auto v5 = y | views::adjacent<5>; VERIFY( ranges::equal(v5, views::single(std::make_tuple(1, 2, 3, 4, 5))) ); diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc index 6aeedbaa648..a5791b3da70 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc @@ -39,6 +39,9 @@ test01() VERIFY( ranges::size(v3) == 4 ); VERIFY( ranges::equal(v3, (int[]){3, 4, 5, 6}) ); + // LWG 3848 - adjacent_transform_view etc missing base accessor + v3.base(); + const auto v6 = y | views::adjacent_transform<6>([](auto...) { return 0; }); VERIFY( ranges::equal(v6, (int[]){0}) ); diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/chunk/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/chunk/1.cc index 90eb608ca5e..82f9f1b674c 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/chunk/1.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/chunk/1.cc @@ -8,6 +8,7 @@ #endif #include +#include #include #include #include @@ -76,10 +77,24 @@ test02() VERIFY( ranges::equal(wrapper(x) | views::chunk(i) | views::join, x) ); } +void +test03() +{ + // LWG 3851 - chunk_view::inner-iterator missing custom iter_move and iter_swap + auto ints = std::istringstream{"0 1 2 3 4"}; + std::vector vs{"the", "quick", "brown", "fox"}; + auto r = views::zip(vs, views::istream(ints)) | views::chunk(2) | views::join; + std::vector> res; + ranges::copy(std::move_iterator(r.begin()), std::move_sentinel(r.end()), + std::back_inserter(res)); + VERIFY( vs.front().empty() ); +} + int main() { static_assert(test01()); test02<__gnu_test::test_input_range>(); test02<__gnu_test::test_forward_range>(); + test03(); } diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/slide/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/slide/1.cc index bafe9fbc4bf..a5d94ea6406 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/slide/1.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/slide/1.cc @@ -50,6 +50,9 @@ test01() VERIFY( &v3[i][2] == &y[i] + 2 ); } + // LWG 3848 - slide_view etc missing base accessor + v3.base(); + const auto v5 = y | views::slide(5); VERIFY( ranges::size(v5) == 1 ); VERIFY( ranges::equal(v5 | views::join, y) ); diff --git a/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc b/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc index bec4174a3da..9db61a76596 100644 --- a/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc +++ b/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc @@ -19,6 +19,7 @@ #include #include +#include #include void @@ -118,6 +119,16 @@ test07() static_assert(!requires { iota(nullptr, nullptr); }); } +void +test08() +{ + // LWC 4001 - iota_view should provide empty + std::vector v; + auto it = std::back_inserter(v); + auto r = std::views::iota(it); + VERIFY( !r.empty() ); +} + int main() { @@ -128,4 +139,5 @@ main() test05(); test06(); test07(); + test08(); } diff --git a/libstdc++-v3/testsuite/std/ranges/repeat/1.cc b/libstdc++-v3/testsuite/std/ranges/repeat/1.cc index cad8c8dcbe7..eb0c848e9ce 100644 --- a/libstdc++-v3/testsuite/std/ranges/repeat/1.cc +++ b/libstdc++-v3/testsuite/std/ranges/repeat/1.cc @@ -151,6 +151,27 @@ test07() auto d2 = std::views::repeat(std::make_unique(5), 4) | std::views::drop(2); } +void +test08() +{ + // LWG 4053 - Unary call to std::views::repeat does not decay the argument + using type = ranges::repeat_view; + using type = decltype(views::repeat("foo", std::unreachable_sentinel)); + using type = decltype(views::repeat(+"foo", std::unreachable_sentinel)); + using type = decltype(views::repeat("foo")); + using type = decltype(views::repeat(+"foo")); +} + +void +test09() +{ + // LWG 4054 - Repeating a repeat_view should repeat the view + auto v = views::repeat(views::repeat(5)); + using type = decltype(v); + using type = ranges::repeat_view>; + VERIFY( v[0][0] == 5 ); +} + int main() { @@ -161,4 +182,6 @@ main() test05(); test06(); test07(); + test08(); + test09(); }