From patchwork Mon Sep 12 16:45:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 1676991 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org 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=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=OqwgiYGT; dkim-atps=neutral Received: from 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 (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4MRCCm01vYz1ynm for ; Tue, 13 Sep 2022 02:46:09 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DC2EE394343C for ; Mon, 12 Sep 2022 16:46:05 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DC2EE394343C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1663001165; bh=YiVfJJKyMFRTPb30HBSDZspjGAT8X/f0ELDYdIUceD0=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=OqwgiYGTRi8DJmhQB0MkphzQ7Lj9rDgI/RuBShY/1XeYG8FKbbG44xH6aEVtGAF3C iMoDz91C+5BylL7XRXMCEN+AF0mH35W1jM0PKaZT9gurd7bCi2UQDwXy7H+Vlrc9AZ kHFJ3al5BOV2hUssgTp+CJs5YzKfMVjqdX+1cy6E= 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.129.124]) by sourceware.org (Postfix) with ESMTPS id 9B1EF3898C6A for ; Mon, 12 Sep 2022 16:45:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 9B1EF3898C6A Received: from mail-qk1-f199.google.com (mail-qk1-f199.google.com [209.85.222.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-13-4xTpAzpfMSyqsz8BzKnvhw-1; Mon, 12 Sep 2022 12:45:40 -0400 X-MC-Unique: 4xTpAzpfMSyqsz8BzKnvhw-1 Received: by mail-qk1-f199.google.com with SMTP id bk21-20020a05620a1a1500b006be9f844c59so7807613qkb.9 for ; Mon, 12 Sep 2022 09:45:40 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date; bh=YiVfJJKyMFRTPb30HBSDZspjGAT8X/f0ELDYdIUceD0=; b=K1+c3CvEw8B0emDgcrR/S9QvKHwHKXcfeRqL1s9/6J5A9dcpKCE0c9LMt+QVnN7rzS wes0cKEsrTmwdp0Pe1iyJJylwqLHERP7pDrzCIXKGZGaBrUSUN2xqIgYFD/qnlOpMf+h lF6kfy1Muz3iJmMrKlmU8vScwKGolw8k1TdZGGhx1Aka9E5/eIdxm9p2YNF4Xdi0AEn3 rGg0rR5eL2OoO8/zE2bS5POGqGuuKt8yDSzsBfAQolNL5BRTmXwcfpUTi0J+wSgA9JRV X75PLwt1OaT5sWTttQ8f0jc3Bdry/if/A5Lg+nvojuvAuQ9NhJbjSBjP7C5Wf+RVIpbR 21zQ== X-Gm-Message-State: ACgBeo0zmALIydNYCC6Zgb60echtPtocrV4SXaPqZj2FyL/r8Q6IPjD0 V7ZB9jfX5a/ng5nKRwwnkyAtgCRgkRZc8Y6qGDQT50QoZwK2wL8ov7fsonx1pRvOIlaHc1zj4pZ cYgC92mFR9M7D3D6mrfuhA09PEMKW8fg9A1ydT6maX07dpALDHj4R4m07KwXcw4qEdQ4= X-Received: by 2002:a05:622a:1650:b0:344:6ec4:739 with SMTP id y16-20020a05622a165000b003446ec40739mr24157481qtj.515.1663001140415; Mon, 12 Sep 2022 09:45:40 -0700 (PDT) X-Google-Smtp-Source: AA6agR5qWgBy3QtoPJxFu7xmHM45wFgluW1ma+GRxnkav8zavDxefMXYvbEiYE4o62xvubA3IRb7Mw== X-Received: by 2002:a05:622a:1650:b0:344:6ec4:739 with SMTP id y16-20020a05622a165000b003446ec40739mr24157454qtj.515.1663001140158; Mon, 12 Sep 2022 09:45:40 -0700 (PDT) Received: from localhost.localdomain (ool-457670bb.dyn.optonline.net. [69.118.112.187]) by smtp.gmail.com with ESMTPSA id 17-20020ac85651000000b0035ba48c032asm6667350qtt.25.2022.09.12.09.45.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 12 Sep 2022 09:45:39 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [PATCH 1/4] libstdc++: Add already-accepted testcase [PR106320] Date: Mon, 12 Sep 2022 12:45:28 -0400 Message-Id: <20220912164531.1742034-1-ppalka@redhat.com> X-Mailer: git-send-email 2.37.3.542.gdd3f6c4cae MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-14.7 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_LOW, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE 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.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Patrick Palka via Gcc-patches From: Patrick Palka Reply-To: Patrick Palka Cc: libstdc++@gcc.gnu.org Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Although PR106320 only affected the 10 and 11 branches, and the testcase from there was already correctly accepted on trunk and the 12 branch, we should also add the testcase to 12/trunk for inter-branch consistency. Tested on x86_64-pc-linux-gnu, does this look OK for trunk/12? PR libstdc++/106320 libstdc++-v3/ChangeLog: * testsuite/std/ranges/adaptors/join.cc (test13): New test. --- libstdc++-v3/testsuite/std/ranges/adaptors/join.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/join.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/join.cc index 8986f718229..530ab6663b5 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/join.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/join.cc @@ -205,6 +205,18 @@ test12() }(); } +void +test13() +{ + // PR libstdc++/106320 + auto l = std::views::transform([](auto x) { + return x | std::views::transform([i=0](auto y) { + return y; + }); + }); + std::vector> v{{5, 6, 7}}; + v | l | std::views::join; +} int main() { @@ -220,4 +232,5 @@ main() test10(); test11(); test12(); + test13(); } From patchwork Mon Sep 12 16:45:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 1676993 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org 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=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=uPwOD1wg; dkim-atps=neutral Received: from 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 (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4MRCDr4zZrz1ynm for ; Tue, 13 Sep 2022 02:47:08 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 76A7E38AA260 for ; Mon, 12 Sep 2022 16:47:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 76A7E38AA260 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1663001226; bh=x4ZYrG2d13Kk/6s+RjiiA6vGLL0TbNaWFHnV4B78tfo=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=uPwOD1wgkuGyq+fx59ONMhzQBJE5yvflE+A3vKz2ffLJfxPiFe14sKg1gWdWxfnkl Pm3YyYAR/HMmQZnI2MQOeU3IUgtImcY2v0w9HiaJoeRqpNfWIR3JLo7KWYGHTFDHT8 zwrV6bx643MkSomB/qaSe1aTUlMOcLDhix9nJndM= 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 ESMTPS id 8A01A38A8152 for ; Mon, 12 Sep 2022 16:45:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8A01A38A8152 Received: from mail-qv1-f69.google.com (mail-qv1-f69.google.com [209.85.219.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-192-widRYh8AOSWUyUuQ_KjxvQ-1; Mon, 12 Sep 2022 12:45:42 -0400 X-MC-Unique: widRYh8AOSWUyUuQ_KjxvQ-1 Received: by mail-qv1-f69.google.com with SMTP id ec8-20020ad44e68000000b004aab01f3eaaso6125772qvb.4 for ; Mon, 12 Sep 2022 09:45:42 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date; bh=x4ZYrG2d13Kk/6s+RjiiA6vGLL0TbNaWFHnV4B78tfo=; b=17ln7Kq1OiivinBHkn2fyj0P1NezbmOHW0mNiQ7RpRXifO/08lIuuZB5NL1lOIEmDT VNUp0DH60SCWgJYXGM0NbtDE4kWVFV05fT+QP5Hk2SqmSvaRnsyWV+0VdZ6lZEofUmF0 Ny9rQ+rbB/qBDAaOqmWkGZMAcEj9E5/ib9SkKGqhirchKLS4InT16y1l0iTGq7SZjggR dkmjMfXO5Ntk03gHkeI1dFGlPWMhjYNqRpkYvWivxgUJwqEobPtb5BiN0e9o53l03iH+ esJIEJaTv9K8MtOOqw5ie34LEkpiPcBU0e/VzuSJYZmITrczacMBdDbH8Is5xbrMZ6H1 0rXg== X-Gm-Message-State: ACgBeo0tzbiuekaSHfddaD5MoFZpTeUNGgo4VccYIim3PNCuxEbJMbYl gZy6HIbCLuPlGXhDFFWvpi40gahpuuMUChXI+c+oT25YUzrWM/mTDoJ7hZtP4tykhPoQC0NugsV +tB42M+FwpGOS5BrgLdWnXZWBzFVHu0FC6gQhElVTXsPwZnef/nXnXuUoSG1BIoR0DBE= X-Received: by 2002:a05:620a:124f:b0:6cd:ef55:544c with SMTP id a15-20020a05620a124f00b006cdef55544cmr9030247qkl.158.1663001141550; Mon, 12 Sep 2022 09:45:41 -0700 (PDT) X-Google-Smtp-Source: AA6agR72NXdqShNtPq4UkzFp+xc+mdTURWXWI/oW1dTRfmrC322S5Zqacw+TbOyUY9y/dkotlDURtQ== X-Received: by 2002:a05:620a:124f:b0:6cd:ef55:544c with SMTP id a15-20020a05620a124f00b006cdef55544cmr9030231qkl.158.1663001141230; Mon, 12 Sep 2022 09:45:41 -0700 (PDT) Received: from localhost.localdomain (ool-457670bb.dyn.optonline.net. [69.118.112.187]) by smtp.gmail.com with ESMTPSA id 17-20020ac85651000000b0035ba48c032asm6667350qtt.25.2022.09.12.09.45.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 12 Sep 2022 09:45:40 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [PATCH 2/4] libstdc++: Implement LWG 3569 changes to join_view::_Iterator Date: Mon, 12 Sep 2022 12:45:29 -0400 Message-Id: <20220912164531.1742034-2-ppalka@redhat.com> X-Mailer: git-send-email 2.37.3.542.gdd3f6c4cae In-Reply-To: <20220912164531.1742034-1-ppalka@redhat.com> References: <20220912164531.1742034-1-ppalka@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-14.3 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_LOW, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham 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.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Patrick Palka via Gcc-patches From: Patrick Palka Reply-To: Patrick Palka Cc: libstdc++@gcc.gnu.org Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Tested on x86_64-pc-linux-gnu, does this look OK for trunk only? libstdc++-v3/ChangeLog: * include/std/ranges (join_view::_Iterator::_M_satisfy): Adjust resetting _M_inner as per LWG 3569. (join_view::_Iterator::_M_inner): Wrap in std::optional as per LWG 3569. (join_view::_Iterator::_Iterator): Relax constraints as per LWG 3569. (join_view::_Iterator::operator*): Adjust as per LWG 3569. (join_view::_Iterator::operator->): Likewise. (join_view::_Iterator::operator++): Likewise. (join_view::_Iterator::operator--): Likewise. (join_view::_Iterator::iter_move): Likewise. (join_view::_Iterator::iter_swap): Likewise. * testsuite/std/ranges/adaptor/join.cc (test14): New test. --- libstdc++-v3/include/std/ranges | 28 +++++++++---------- .../testsuite/std/ranges/adaptors/join.cc | 17 +++++++++++ 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 20eb4e82ac8..6297ce7cee3 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -2746,7 +2746,7 @@ namespace views::__adaptor } if constexpr (_S_ref_is_glvalue) - _M_inner = _Inner_iter(); + _M_inner.reset(); } static constexpr auto @@ -2769,7 +2769,7 @@ namespace views::__adaptor using _Inner_iter = join_view::_Inner_iter<_Const>; _Outer_iter _M_outer = _Outer_iter(); - _Inner_iter _M_inner = _Inner_iter(); + optional<_Inner_iter> _M_inner; _Parent* _M_parent = nullptr; public: @@ -2780,9 +2780,7 @@ namespace views::__adaptor = common_type_t, range_difference_t>>; - _Iterator() requires (default_initializable<_Outer_iter> - && default_initializable<_Inner_iter>) - = default; + _Iterator() requires default_initializable<_Outer_iter> = default; constexpr _Iterator(_Parent* __parent, _Outer_iter __outer) @@ -2801,7 +2799,7 @@ namespace views::__adaptor constexpr decltype(auto) operator*() const - { return *_M_inner; } + { return **_M_inner; } // _GLIBCXX_RESOLVE_LIB_DEFECTS // 3500. join_view::iterator::operator->() is bogus @@ -2809,7 +2807,7 @@ namespace views::__adaptor operator->() const requires __detail::__has_arrow<_Inner_iter> && copyable<_Inner_iter> - { return _M_inner; } + { return *_M_inner; } constexpr _Iterator& operator++() @@ -2820,7 +2818,7 @@ namespace views::__adaptor else return *_M_parent->_M_inner; }(); - if (++_M_inner == ranges::end(__inner_range)) + if (++*_M_inner == ranges::end(__inner_range)) { ++_M_outer; _M_satisfy(); @@ -2850,9 +2848,9 @@ namespace views::__adaptor { if (_M_outer == ranges::end(_M_parent->_M_base)) _M_inner = ranges::end(*--_M_outer); - while (_M_inner == ranges::begin(*_M_outer)) - _M_inner = ranges::end(*--_M_outer); - --_M_inner; + while (*_M_inner == ranges::begin(*_M_outer)) + *_M_inner = ranges::end(*--_M_outer); + --*_M_inner; return *this; } @@ -2879,14 +2877,14 @@ namespace views::__adaptor friend constexpr decltype(auto) iter_move(const _Iterator& __i) - noexcept(noexcept(ranges::iter_move(__i._M_inner))) - { return ranges::iter_move(__i._M_inner); } + noexcept(noexcept(ranges::iter_move(*__i._M_inner))) + { return ranges::iter_move(*__i._M_inner); } friend constexpr void iter_swap(const _Iterator& __x, const _Iterator& __y) - noexcept(noexcept(ranges::iter_swap(__x._M_inner, __y._M_inner))) + noexcept(noexcept(ranges::iter_swap(*__x._M_inner, *__y._M_inner))) requires indirectly_swappable<_Inner_iter> - { return ranges::iter_swap(__x._M_inner, __y._M_inner); } + { return ranges::iter_swap(*__x._M_inner, *__y._M_inner); } friend _Iterator; template friend struct _Sentinel; diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/join.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/join.cc index 530ab6663b5..afc11d4bd7a 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/join.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/join.cc @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -217,6 +218,21 @@ test13() std::vector> v{{5, 6, 7}}; v | l | std::views::join; } + +void +test14() +{ + // LWG 3569: join_view fails to support ranges of ranges with + // non-default_initializable iterators + auto ss = std::istringstream{"1 2 3"}; + auto v = views::single(views::istream(ss)); + using inner = ranges::range_reference_t; + static_assert(ranges::input_range + && !ranges::forward_range + && !std::default_initializable>); + VERIFY( ranges::equal(v | views::join, (int[]){1, 2, 3}) ); +} + int main() { @@ -233,4 +249,5 @@ main() test11(); test12(); test13(); + test14(); } From patchwork Mon Sep 12 16:45:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 1676992 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=laNNwALq; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4MRCCq406Hz1ypL for ; Tue, 13 Sep 2022 02:46:13 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 28AD938AA277 for ; Mon, 12 Sep 2022 16:46:11 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 28AD938AA277 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1663001171; bh=q4fv7jvzYnJ4FhYE1dAxfiEnUn/zQ17yyUxwt5vlDVw=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=laNNwALqffuxcSkQBleKE19l0iU47FIcJq1kzbewuwCkhPjhNxmMTercVMDVBFPAM UBl9/slFcm+8naJCarCVr3uT9K3fIOE4omSjJE6ueX/IYmDmPfLyj3VS70GCGIY5tV JjR3pjv27z/3csq1bjWp2PFNP3ShXwlJVN5GdXPw= 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.129.124]) by sourceware.org (Postfix) with ESMTPS id 8E9A938A908C for ; Mon, 12 Sep 2022 16:45:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8E9A938A908C Received: from mail-qk1-f198.google.com (mail-qk1-f198.google.com [209.85.222.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-383-BsJ8ZIZUMNGUvB9_pnMc-A-1; Mon, 12 Sep 2022 12:45:43 -0400 X-MC-Unique: BsJ8ZIZUMNGUvB9_pnMc-A-1 Received: by mail-qk1-f198.google.com with SMTP id bj2-20020a05620a190200b006bba055ab6eso7826696qkb.12 for ; Mon, 12 Sep 2022 09:45:43 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date; bh=q4fv7jvzYnJ4FhYE1dAxfiEnUn/zQ17yyUxwt5vlDVw=; b=JegfUr+p5mtBCpa5u2s/mu+h3HGhnT+yFtWQh7g9tz1agtMUaPX+7ISTjTkeyH6duu aH5h/JQEoZsJ6VVPa9cyRcwagzaEuxUrpgO1uun1eGQSsS68idLpKkzS4jTrluxkZy7K G/SJAEYH73JBUZypFetMgXzZRCfRRJVJHMy/vhwJCA2Q1qWLk5i7qS6Uae3vsaoGoJNZ xcugtlWpdpc90+gSXxVKQb1EGcQnLjd/CZ2O7zqNqSJ2yNRXZBjxWtfWtniiqX34dr8T z9y7VGNzYWPeW3wdtn10vbaXRiOKILmn070MyCIi2SjY1s+wmJf5V/Sthpq5V0j2N8xw CW1g== X-Gm-Message-State: ACgBeo1MUz3xG0P7xv4wxrJFo3w+Bi9W0/gXh/AzYR1h0HC5CT43iJx5 w3eITi7VHc67wD84KQKhh7apzzPVvS/Sifja5aoVm+vimfHwT6JUv6BF+nHcsRgaMyalUafsTcC cLO1kIsL0hNdPVZ++FFOII15uU/AGJVy8JtrOGgSTvsQeRbYoF9jALCuPxluzvSgm0Ok= X-Received: by 2002:a05:620a:4409:b0:6bb:beeb:215e with SMTP id v9-20020a05620a440900b006bbbeeb215emr20257305qkp.414.1663001142983; Mon, 12 Sep 2022 09:45:42 -0700 (PDT) X-Google-Smtp-Source: AA6agR6MolP0yUuSKvnS0GHNFNNtKHQ8y3vWPEzEWz5dYqOb103o4v0i0NN7dCwAHrb6RhJIR6416g== X-Received: by 2002:a05:620a:4409:b0:6bb:beeb:215e with SMTP id v9-20020a05620a440900b006bbbeeb215emr20257272qkp.414.1663001142530; Mon, 12 Sep 2022 09:45:42 -0700 (PDT) Received: from localhost.localdomain (ool-457670bb.dyn.optonline.net. [69.118.112.187]) by smtp.gmail.com with ESMTPSA id 17-20020ac85651000000b0035ba48c032asm6667350qtt.25.2022.09.12.09.45.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 12 Sep 2022 09:45:42 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [PATCH 3/4] libstdc++: Implement ranges::chunk_view from P2442R1 Date: Mon, 12 Sep 2022 12:45:30 -0400 Message-Id: <20220912164531.1742034-3-ppalka@redhat.com> X-Mailer: git-send-email 2.37.3.542.gdd3f6c4cae In-Reply-To: <20220912164531.1742034-1-ppalka@redhat.com> References: <20220912164531.1742034-1-ppalka@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-14.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_NUMSUBJECT, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham 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.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Patrick Palka via Gcc-patches From: Patrick Palka Reply-To: Patrick Palka Cc: libstdc++@gcc.gnu.org Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" This also implements the LWG 3707, 3710 and 3712 changes to chunk_view. libstdc++-v3/ChangeLog: * include/std/ranges (__detail::__div_ceil): Define. (chunk_view): Define. (chunk_view::_OuterIter): Define. (chunk_view::_OuterIter::value_type): Define. (chunk_view::_InnerIter): Define. (chunk_view<_Vp>): Define partial specialization for forward ranges. (enable_borrowed_range): Define. (chunk_view<_Vp>::_Iterator): Define. (views::__detail::__can_chunk_view): Define. (views::_Chunk, views::chunk): Define. * testsuite/std/ranges/adaptors/chunk/1.cc: New test. --- libstdc++-v3/include/std/ranges | 538 ++++++++++++++++++ .../testsuite/std/ranges/adaptors/chunk/1.cc | 80 +++ 2 files changed, 618 insertions(+) create mode 100644 libstdc++-v3/testsuite/std/ranges/adaptors/chunk/1.cc diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 6297ce7cee3..7533b60c1d6 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -5776,6 +5776,544 @@ namespace views::__adaptor inline constexpr auto pairwise_transform = adjacent_transform<2>; } + + namespace __detail + { + template + constexpr _Tp __div_ceil(_Tp __num, _Tp __denom) + { + _Tp __r = __num / __denom; + if (__num % __denom) + ++__r; + return __r; + } + } + + template + requires input_range<_Vp> + class chunk_view : public view_interface> + { + _Vp _M_base; + range_difference_t<_Vp> _M_n; + range_difference_t<_Vp> _M_remainder = 0; + __detail::__non_propagating_cache> _M_current; + + class _OuterIter; + class _InnerIter; + + public: + constexpr explicit + chunk_view(_Vp __base, range_difference_t<_Vp> __n) + : _M_base(std::move(__base)), _M_n(__n) + { __glibcxx_assert(__n >= 0); } + + constexpr _Vp + base() const & requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr _OuterIter + begin() + { + _M_current = ranges::begin(_M_base); + _M_remainder = _M_n; + return _OuterIter(*this); + } + + constexpr default_sentinel_t + end() const noexcept + { return default_sentinel; } + + constexpr auto + size() requires sized_range<_Vp> + { + return __detail::__to_unsigned_like(__detail::__div_ceil + (ranges::distance(_M_base), _M_n)); + } + + constexpr auto + size() const requires sized_range + { + return __detail::__to_unsigned_like(__detail::__div_ceil + (ranges::distance(_M_base), _M_n)); + } + }; + + template + chunk_view(_Range&&, range_difference_t<_Range>) -> chunk_view>; + + template + requires input_range<_Vp> + class chunk_view<_Vp>::_OuterIter + { + chunk_view* _M_parent; + + constexpr explicit + _OuterIter(chunk_view& __parent) + : _M_parent(std::__addressof(__parent)) + { } + + friend chunk_view; + + public: + using iterator_concept = input_iterator_tag; + using difference_type = range_difference_t<_Vp>; + + struct value_type; + + _OuterIter(_OuterIter&&) = default; + _OuterIter& operator=(_OuterIter&&) = default; + + constexpr value_type + operator*() const + { + __glibcxx_assert(*this != default_sentinel); + return value_type(*_M_parent); + } + + constexpr _OuterIter& + operator++() + { + __glibcxx_assert(*this != default_sentinel); + ranges::advance(*_M_parent->_M_current, _M_parent->_M_remainder, + ranges::end(_M_parent->_M_base)); + _M_parent->_M_remainder = _M_parent->_M_n; + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + friend constexpr bool + operator==(const _OuterIter& __x, default_sentinel_t) + { + return *__x._M_parent->_M_current == ranges::end(__x._M_parent->_M_base) + && __x._M_parent->_M_remainder != 0; + } + + friend constexpr difference_type + operator-(default_sentinel_t, const _OuterIter& __x) + requires sized_sentinel_for, iterator_t<_Vp>> + { + const auto __dist = ranges::end(__x._M_parent->_M_base) - *__x._M_parent->_M_current; + + if (__dist < __x._M_parent->_M_remainder) + return __dist == 0 ? 0 : 1; + + return 1 + __detail::__div_ceil(__dist - __x._M_parent->_M_remainder, + __x._M_parent->_M_n); + } + + friend constexpr difference_type + operator-(const _OuterIter& __x, default_sentinel_t __y) + requires sized_sentinel_for, iterator_t<_Vp>> + { return -(__y - __x); } + }; + + template + requires input_range<_Vp> + struct chunk_view<_Vp>::_OuterIter::value_type : view_interface + { + private: + chunk_view* _M_parent; + + constexpr explicit + value_type(chunk_view& __parent) + : _M_parent(std::__addressof(__parent)) + { } + + friend _OuterIter; + + public: + constexpr _InnerIter + begin() const noexcept + { return _InnerIter(*_M_parent); } + + constexpr default_sentinel_t + end() const noexcept + { return default_sentinel; } + + constexpr auto + size() const + requires sized_sentinel_for, iterator_t<_Vp>> + { + return __detail::__to_unsigned_like + (ranges::min(_M_parent->_M_remainder, + ranges::end(_M_parent->_M_base) - *_M_parent->_M_current)); + } + }; + + template + requires input_range<_Vp> + class chunk_view<_Vp>::_InnerIter + { + chunk_view* _M_parent; + + constexpr explicit + _InnerIter(chunk_view& __parent) noexcept + : _M_parent(std::__addressof(__parent)) + { } + + friend _OuterIter::value_type; + + public: + using iterator_concept = input_iterator_tag; + using difference_type = range_difference_t<_Vp>; + using value_type = range_value_t<_Vp>; + + _InnerIter(_InnerIter&&) = default; + _InnerIter& operator=(_InnerIter&&) = default; + + constexpr const iterator_t<_Vp>& + base() const & + { return *_M_parent->_M_current; } + + constexpr range_reference_t<_Vp> + operator*() const + { + __glibcxx_assert(*this != default_sentinel); + return **_M_parent->_M_current; + } + + constexpr _InnerIter& + operator++() + { + __glibcxx_assert(*this != default_sentinel); + ++*_M_parent->_M_current; + if (*_M_parent->_M_current == ranges::end(_M_parent->_M_base)) + _M_parent->_M_remainder = 0; + else + --_M_parent->_M_remainder; + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + friend constexpr bool + operator==(const _InnerIter& __x, default_sentinel_t) + { return __x._M_parent->_M_remainder == 0; } + + friend constexpr difference_type + operator-(default_sentinel_t, const _InnerIter& __x) + requires sized_sentinel_for, iterator_t<_Vp>> + { + return ranges::min(__x._M_parent->_M_remainder, + ranges::end(__x._M_parent->_M_base) - *__x._M_parent->_M_current); + } + + friend constexpr difference_type + operator-(const _InnerIter& __x, default_sentinel_t __y) + requires sized_sentinel_for, iterator_t<_Vp>> + { return -(__y - __x); } + }; + + template + requires forward_range<_Vp> + class chunk_view<_Vp> : public view_interface> + { + _Vp _M_base; + range_difference_t<_Vp> _M_n; + template class _Iterator; + + public: + constexpr explicit + chunk_view(_Vp __base, range_difference_t<_Vp> __n) + : _M_base(std::move(__base)), _M_n(__n) + { __glibcxx_assert(__n > 0); } + + 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(this, ranges::begin(_M_base)); } + + constexpr auto + begin() const requires forward_range + { return _Iterator(this, ranges::begin(_M_base)); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { + if constexpr (common_range<_Vp> && sized_range<_Vp>) + { + auto __missing = (_M_n - ranges::distance(_M_base) % _M_n) % _M_n; + return _Iterator(this, ranges::end(_M_base), __missing); + } + else if constexpr (common_range<_Vp> && !bidirectional_range<_Vp>) + return _Iterator(this, ranges::end(_M_base)); + else + return default_sentinel; + } + + constexpr auto + end() const requires forward_range + { + if constexpr (common_range && sized_range) + { + auto __missing = (_M_n - ranges::distance(_M_base) % _M_n) % _M_n; + return _Iterator(this, ranges::end(_M_base), __missing); + } + else if constexpr (common_range && !bidirectional_range) + return _Iterator(this, ranges::end(_M_base)); + else + return default_sentinel; + } + + constexpr auto + size() requires sized_range<_Vp> + { + return __detail::__to_unsigned_like(__detail::__div_ceil + (ranges::distance(_M_base), _M_n)); + } + + constexpr auto + size() const requires sized_range + { + return __detail::__to_unsigned_like(__detail::__div_ceil + (ranges::distance(_M_base), _M_n)); + } + }; + + template + inline constexpr bool enable_borrowed_range> + = forward_range<_Vp> && enable_borrowed_range<_Vp>; + + template + requires forward_range<_Vp> + template + class chunk_view<_Vp>::_Iterator + { + using _Parent = __detail::__maybe_const_t<_Const, chunk_view>; + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + iterator_t<_Base> _M_current = iterator_t<_Base>(); + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + range_difference_t<_Base> _M_n = 0; + range_difference_t<_Base> _M_missing = 0; + + constexpr + _Iterator(_Parent* __parent, iterator_t<_Base> __current, + range_difference_t<_Base> __missing = 0) + : _M_current(__current), _M_end(ranges::end(__parent->_M_base)), + _M_n(__parent->_M_n), _M_missing(__missing) + { } + + static auto + _S_iter_cat() + { + if constexpr (random_access_range<_Base>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_range<_Base>) + return bidirectional_iterator_tag{}; + else + return forward_iterator_tag{}; + } + + friend chunk_view; + + public: + using iterator_category = input_iterator_tag; + using iterator_concept = decltype(_S_iter_cat()); + using value_type = decltype(views::take(subrange(_M_current, _M_end), _M_n)); + using difference_type = range_difference_t<_Base>; + + _Iterator() = default; + + constexpr _Iterator(_Iterator __i) + requires _Const + && convertible_to, iterator_t<_Base>> + && convertible_to, sentinel_t<_Base>> + : _M_current(std::move(__i._M_current)), _M_end(std::move(__i._M_end)), + _M_n(__i._M_n), _M_missing(__i._M_missing) + { } + + constexpr iterator_t<_Base> + base() const + { return _M_current; } + + constexpr value_type + operator*() const + { + __glibcxx_assert(_M_current != _M_end); + return views::take(subrange(_M_current, _M_end), _M_n); + } + + constexpr _Iterator& + operator++() + { + __glibcxx_assert(_M_current != _M_end); + _M_missing = ranges::advance(_M_current, _M_n, _M_end); + return *this; + } + + constexpr _Iterator + operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + ranges::advance(_M_current, _M_missing - _M_n); + _M_missing = 0; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) + requires random_access_range<_Base> + { + if (__x > 0) + { + __glibcxx_assert(ranges::distance(_M_current, _M_end) > _M_n * (__x - 1)); + _M_missing = ranges::advance(_M_current, _M_n * __x, _M_end); + } + else if (__x < 0) + { + ranges::advance(_M_current, _M_n * __x + _M_missing); + _M_missing = 0; + } + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) + requires random_access_range<_Base> + { return *this += -__x; } + + constexpr value_type + operator[](difference_type __n) const + requires random_access_range<_Base> + { return *(*this + __n); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + { return __x._M_current == __y._M_current; } + + friend constexpr bool + operator==(const _Iterator& __x, default_sentinel_t) + { return __x._M_current == __x._M_end; } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current > __y._M_current; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y < __x; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__y < __x); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__x < __y); } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + && three_way_comparable> + { return __x._M_current <=> __y._M_current; } + + friend constexpr _Iterator + operator+(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator+(difference_type __n, const _Iterator& __i) + requires random_access_range<_Base> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator-(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + auto __r = __i; + __r -= __n; + return __r; + } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires sized_sentinel_for, iterator_t<_Base>> + { + return (__x._M_current - __y._M_current + + __x._M_missing - __y._M_missing) / __x._M_n; + } + + friend constexpr difference_type + operator-(default_sentinel_t __y, const _Iterator& __x) + requires sized_sentinel_for, iterator_t<_Base>> + { return __detail::__div_ceil(__x._M_end - __x._M_current, __x._M_n); } + + friend constexpr difference_type + operator-(const _Iterator& __x, default_sentinel_t __y) + requires sized_sentinel_for, iterator_t<_Base>> + { return -(__y - __x); } + }; + + namespace views + { + namespace __detail + { + template + concept __can_chunk_view + = requires { chunk_view(std::declval<_Range>(), std::declval<_Dp>()); }; + } + + struct _Chunk : __adaptor::_RangeAdaptor<_Chunk> + { + template> + requires __detail::__can_chunk_view<_Range, _Dp> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, type_identity_t<_Dp> __n) const + { return chunk_view(std::forward<_Range>(__r), __n); } + + using __adaptor::_RangeAdaptor<_Chunk>::operator(); + static constexpr int _S_arity = 2; + static constexpr bool _S_has_simple_extra_args = true; + }; + + inline constexpr _Chunk chunk; + } + #endif // C++23 } // namespace ranges diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/chunk/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/chunk/1.cc new file mode 100644 index 00000000000..125c88ef853 --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/chunk/1.cc @@ -0,0 +1,80 @@ +// { dg-options "-std=gnu++23" } +// { dg-do run { target c++23 } } + +#include +#include +#include +#include +#include + +namespace ranges = std::ranges; +namespace views = std::views; + +constexpr bool +test01() +{ + int x[] = {1, 2, 3, 4, 5}; + + auto v2 = x | views::chunk(2); + const auto i0 = v2.begin(), i1 = v2.begin() + 1; + VERIFY( i0 + 1 - 1 == i0 ); + VERIFY( i0 < i1 ); + VERIFY( i1 < v2.end() ); + VERIFY( i1 - i0 == 1 ); + VERIFY( i0 - i1 == -1 ); + VERIFY( v2.end() - i1 == 2 ); + VERIFY( i1 - v2.end() == -2 ); + auto i2 = v2.begin(); + i2 += 2; + i2 -= -1; + VERIFY( i2 == v2.end() ); + VERIFY( ranges::size(v2) == 3 ); + VERIFY( ranges::equal(v2, (std::initializer_list[]){{1, 2}, {3, 4}, {5}}, + ranges::equal) ); + + auto v1 = x | views::chunk(1); + VERIFY( ranges::size(v1) == ranges::size(x) ); + for (auto [r, n] : views::zip(v1, x)) + { + VERIFY( ranges::size(r) == 1 ); + VERIFY( *r.begin() == n ); + } + + auto v5 = x | views::chunk(5); + VERIFY( ranges::size(v5) == 1 ); + VERIFY( ranges::equal(v5[0], (int[]){1, 2, 3, 4, 5}) ); + + auto v10 = x | views::chunk(10); + VERIFY( ranges::size(v10) == 1 ); + VERIFY( ranges::equal(v10[0], (int[]){1, 2, 3, 4, 5}) ); + + return true; +} + +template +void +test02() +{ + int x[] = {1, 2, 3, 4, 5, 6, 7, 8}; + wrapper rx(x); + auto v = rx | views::chunk(3); + auto i = ranges::begin(v); + VERIFY( ranges::equal(*i, (int[]){1, 2, 3}) ); + ++i; + VERIFY( ranges::equal(*i, (int[]){4, 5, 6}) ); + ++i; + VERIFY( ranges::equal(*i, (int[]){7, 8}) ); + i++; + VERIFY( i == ranges::end(v) ); + + for (int i = 1; i <= 10; ++i) + VERIFY( ranges::equal(wrapper(x) | views::chunk(i) | views::join, x) ); +} + +int +main() +{ + static_assert(test01()); + test02<__gnu_test::test_input_range>(); + test02<__gnu_test::test_forward_range>(); +} From patchwork Mon Sep 12 16:45:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 1676994 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org 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=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=tS/QTg47; dkim-atps=neutral Received: from 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 (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4MRCDy3NC5z1ypL for ; Tue, 13 Sep 2022 02:47:14 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 710DB38AA266 for ; Mon, 12 Sep 2022 16:47:12 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 710DB38AA266 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1663001232; bh=L+EwGAsQOiPwZ1pW6C+ftRBmzrK06rWUBgz2uYYZ23g=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=tS/QTg47+mWJx930vtblCtaZApZo2WCHM74XGE5++SDa7Ts94os6Kcjnh14RhaMIh rUJE/XK8//fulSq6Mp7UzWEf6LKztLRuPvx5RId/WutNhvKGf5b4zVGNePdy92PtxS LgNIHLiaYAd20KHq4+yQx+Q7ciwU0LRrP5vd775U= 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 ESMTPS id 1A08F38A90AE for ; Mon, 12 Sep 2022 16:45:48 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 1A08F38A90AE Received: from mail-qk1-f200.google.com (mail-qk1-f200.google.com [209.85.222.200]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-452-q752GvOaPoeC3aTVR_Mf1A-1; Mon, 12 Sep 2022 12:45:44 -0400 X-MC-Unique: q752GvOaPoeC3aTVR_Mf1A-1 Received: by mail-qk1-f200.google.com with SMTP id bl17-20020a05620a1a9100b006cdf19243acso5506617qkb.4 for ; Mon, 12 Sep 2022 09:45:44 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date; bh=L+EwGAsQOiPwZ1pW6C+ftRBmzrK06rWUBgz2uYYZ23g=; b=k4UJ64QZUw+GXmr5wnPauyC1oEQbrYnbU3eYir9dnMi8aEGM9vRJMxDP11TbEh/ImU GKpZe84xXbokA3JhRyvQNMODNMyL6fqgzxYDP50qflG0caxAWKE2h+QiYn7J89yJrmn0 FLlcuXVbDaz5r7nzEwGvh1im7HehAgZuvqNlYm3Rg6DCcDrfmSjUP++1rZ16Zw1Jf9S4 gN6fGel1nOTZWljx7zcFGzsRb1grPahMgTsHGII898mvZXrg+hXQmruRsDpjWOrnXKOC HgrdG0wUvYZYojBMNGDo2euBydxg8vWe3gksFysbUrgZ5xC59UNp6iCr2OtENbGkykEV WYmA== X-Gm-Message-State: ACgBeo2Q7/ruO4bPX2a8xpWHT8euKlrQo5MnnBRoZOOSHSSZadNB8Rud Exp+K1zMix6EEGRFFnFDEsxqqW8tZFK3JzYI1xlUR2WWbISWb5+KEeXPETKxNiJIlXsxtoojRp7 AspvOAkkBZFsPhfEc6ASDXYh378ZaBvoQVMNZqUSjsrv/jBjdAfykK1d7i3t6RcfOtSw= X-Received: by 2002:a37:395:0:b0:6cd:cca6:4b8a with SMTP id 143-20020a370395000000b006cdcca64b8amr10704733qkd.573.1663001144080; Mon, 12 Sep 2022 09:45:44 -0700 (PDT) X-Google-Smtp-Source: AA6agR70DyH5DOWCmbMnTyFWI7NBDXFhxZ8pcm2+SHhzWNq2fAS76s6hjONiHac3jgrmD4LATlJzgQ== X-Received: by 2002:a37:395:0:b0:6cd:cca6:4b8a with SMTP id 143-20020a370395000000b006cdcca64b8amr10704709qkd.573.1663001143650; Mon, 12 Sep 2022 09:45:43 -0700 (PDT) Received: from localhost.localdomain (ool-457670bb.dyn.optonline.net. [69.118.112.187]) by smtp.gmail.com with ESMTPSA id 17-20020ac85651000000b0035ba48c032asm6667350qtt.25.2022.09.12.09.45.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 12 Sep 2022 09:45:43 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [PATCH 4/4] libstdc++: Implement ranges::slide_view from P2442R1 Date: Mon, 12 Sep 2022 12:45:31 -0400 Message-Id: <20220912164531.1742034-4-ppalka@redhat.com> X-Mailer: git-send-email 2.37.3.542.gdd3f6c4cae In-Reply-To: <20220912164531.1742034-1-ppalka@redhat.com> References: <20220912164531.1742034-1-ppalka@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-14.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_NUMSUBJECT, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE 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.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Patrick Palka via Gcc-patches From: Patrick Palka Reply-To: Patrick Palka Cc: libstdc++@gcc.gnu.org Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" This also implements the LWG 3711 and 3712 changes to slide_view. libstdc++-v3/ChangeLog: * include/std/ranges (__detail::__slide_caches_nothing): Define. (__detail::__slide_caches_last): Define. (__detail::__slide_caches_first): Define. (slide_view): Define. (enable_borrowed_range): Define. (slide_view::_Iterator): Define. (slide_view::_Sentinel): Define. (views::__detail::__can_slide_view): Define. (views::_Slide, views::slide): Define. * testsuite/std/ranges/adaptors/slide/1.cc: New test. --- libstdc++-v3/include/std/ranges | 364 ++++++++++++++++++ .../testsuite/std/ranges/adaptors/slide/1.cc | 105 +++++ 2 files changed, 469 insertions(+) create mode 100644 libstdc++-v3/testsuite/std/ranges/adaptors/slide/1.cc diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 7533b60c1d6..bbe4fa278d2 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -6314,6 +6314,370 @@ namespace views::__adaptor inline constexpr _Chunk chunk; } + namespace __detail + { + template + concept __slide_caches_nothing = random_access_range<_Vp> && sized_range<_Vp>; + + template + concept __slide_caches_last + = !__slide_caches_nothing<_Vp> && bidirectional_range<_Vp> && common_range<_Vp>; + + template + concept __slide_caches_first + = !__slide_caches_nothing<_Vp> && !__slide_caches_last<_Vp>; + } + + template + requires view<_Vp> + class slide_view : public view_interface> + { + _Vp _M_base; + range_difference_t<_Vp> _M_n; + [[no_unique_address]] + __detail::__maybe_present_t<__detail::__slide_caches_first<_Vp>, + __detail::_CachedPosition<_Vp>> _M_cached_begin; + [[no_unique_address]] + __detail::__maybe_present_t<__detail::__slide_caches_last<_Vp>, + __detail::_CachedPosition<_Vp>> _M_cached_end; + + template class _Iterator; + class _Sentinel; + + public: + constexpr explicit + slide_view(_Vp __base, range_difference_t<_Vp> __n) + : _M_base(std::move(__base)), _M_n(__n) + { __glibcxx_assert(__n > 0); } + + constexpr auto + begin() requires (!(__detail::__simple_view<_Vp> + && __detail::__slide_caches_nothing)) + { + if constexpr (__detail::__slide_caches_first<_Vp>) + { + iterator_t<_Vp> __it; + if (_M_cached_begin._M_has_value()) + __it = _M_cached_begin._M_get(_M_base); + else + { + __it = ranges::next(ranges::begin(_M_base), _M_n - 1, ranges::end(_M_base)); + _M_cached_begin._M_set(_M_base, __it); + } + return _Iterator(ranges::begin(_M_base), std::move(__it), _M_n); + } + else + return _Iterator(ranges::begin(_M_base), _M_n); + } + + constexpr auto + begin() const requires __detail::__slide_caches_nothing + { return _Iterator(ranges::begin(_M_base), _M_n); } + + constexpr auto + end() requires (!(__detail::__simple_view<_Vp> + && __detail::__slide_caches_nothing)) + { + if constexpr (__detail::__slide_caches_nothing<_Vp>) + return _Iterator(ranges::begin(_M_base) + range_difference_t<_Vp>(size()), + _M_n); + else if constexpr (__detail::__slide_caches_last<_Vp>) + { + iterator_t<_Vp> __it; + if (_M_cached_end._M_has_value()) + __it = _M_cached_end._M_get(_M_base); + else + { + __it = ranges::prev(ranges::end(_M_base), _M_n - 1, + ranges::begin(_M_base)); + _M_cached_end._M_set(_M_base, __it); + } + return _Iterator(std::move(__it), _M_n); + } + else if constexpr (common_range<_Vp>) + return _Iterator(ranges::end(_M_base), ranges::end(_M_base), _M_n); + else + return _Sentinel(ranges::end(_M_base)); + } + + constexpr auto + end() const requires __detail::__slide_caches_nothing + { return begin() + range_difference_t(size()); } + + constexpr auto + size() requires sized_range<_Vp> + { + auto __sz = ranges::distance(_M_base) - _M_n + 1; + if (__sz < 0) + __sz = 0; + return __detail::__to_unsigned_like(__sz); + } + + constexpr auto + size() const requires sized_range + { + auto __sz = ranges::distance(_M_base) - _M_n + 1; + if (__sz < 0) + __sz = 0; + return __detail::__to_unsigned_like(__sz); + } + }; + + template + slide_view(_Range&&, range_difference_t<_Range>) -> slide_view>; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Vp>; + + template + requires view<_Vp> + template + class slide_view<_Vp>::_Iterator + { + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + static constexpr bool _S_last_elt_present + = __detail::__slide_caches_first<_Base>; + + iterator_t<_Base> _M_current = iterator_t<_Base>(); + [[no_unique_address]] + __detail::__maybe_present_t<_S_last_elt_present, iterator_t<_Base>> + _M_last_elt = decltype(_M_last_elt)(); + range_difference_t<_Base> _M_n = 0; + + constexpr + _Iterator(iterator_t<_Base> __current, range_difference_t<_Base> __n) + requires (!_S_last_elt_present) + : _M_current(__current), _M_n(__n) + { } + + constexpr + _Iterator(iterator_t<_Base> __current, iterator_t<_Base> __last_elt, + range_difference_t<_Base> __n) + requires _S_last_elt_present + : _M_current(__current), _M_last_elt(__last_elt), _M_n(__n) + { } + + static auto + _S_iter_concept() + { + if constexpr (random_access_range<_Base>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_range<_Base>) + return bidirectional_iterator_tag{}; + else + return forward_iterator_tag{}; + } + + friend slide_view; + friend slide_view::_Sentinel; + + public: + using iterator_category = input_iterator_tag; + using iterator_concept = decltype(_S_iter_concept()); + using value_type = decltype(views::counted(_M_current, _M_n)); + using difference_type = range_difference_t<_Base>; + + _Iterator() = default; + + constexpr + _Iterator(_Iterator __i) + requires _Const && convertible_to, iterator_t<_Base>> + : _M_current(std::move(__i._M_current)), _M_n(__i._M_n) + { } + + constexpr auto + operator*() const + { return views::counted(_M_current, _M_n); } + + constexpr _Iterator& + operator++() + { + ++_M_current; + if constexpr (_S_last_elt_present) + ++_M_last_elt; + return *this; + } + + constexpr _Iterator + operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + --_M_current; + if constexpr (_S_last_elt_present) + --_M_last_elt; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) + requires random_access_range<_Base> + { + _M_current += __x; + if constexpr (_S_last_elt_present) + _M_last_elt += __x; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) + requires random_access_range<_Base> + { + _M_current -= __x; + if constexpr (_S_last_elt_present) + _M_last_elt -= __x; + return *this; + } + + constexpr auto + operator[](difference_type __n) const + requires random_access_range<_Base> + { return views::counted(_M_current + __n, _M_n); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + { + if constexpr (_S_last_elt_present) + return __x._M_last_elt == __y._M_last_elt; + else + return __x._M_current == __y._M_current; + } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current < __y._M_current; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y < __x; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__y < __x); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__x < __y); } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + && three_way_comparable> + { return __x._M_current <=> __y._M_current; } + + friend constexpr _Iterator + operator+(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator+(difference_type __n, const _Iterator& __i) + requires random_access_range<_Base> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator-(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + auto __r = __i; + __r -= __n; + return __r; + } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires sized_sentinel_for, iterator_t<_Base>> + { + if constexpr (_S_last_elt_present) + return __x._M_last_elt - __y._M_last_elt; + else + return __x._M_current - __y._M_current; + } + }; + + template + requires view<_Vp> + class slide_view<_Vp>::_Sentinel + { + sentinel_t<_Vp> _M_end = sentinel_t<_Vp>(); + + constexpr explicit + _Sentinel(sentinel_t<_Vp> __end) + : _M_end(__end) + { } + + friend slide_view; + + public: + _Sentinel() = default; + + friend constexpr bool + operator==(const _Iterator& __x, const _Sentinel& __y) + { return __x._M_last_elt == __y._M_end; } + + friend constexpr range_difference_t<_Vp> + operator-(const _Iterator& __x, const _Sentinel& __y) + requires sized_sentinel_for, iterator_t<_Vp>> + { return __x._M_last_elt - __y._M_end; } + + friend constexpr range_difference_t<_Vp> + operator-(const _Sentinel& __y, const _Iterator& __x) + requires sized_sentinel_for, iterator_t<_Vp>> + { return __y._M_end -__x._M_last_elt; } + }; + + namespace views + { + namespace __detail + { + template + concept __can_slide_view + = requires { slide_view(std::declval<_Range>(), std::declval<_Dp>()); }; + } + + struct _Slide : __adaptor::_RangeAdaptor<_Slide> + { + template> + requires __detail::__can_slide_view<_Range, _Dp> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, type_identity_t<_Dp> __n) const + { return slide_view(std::forward<_Range>(__r), __n); } + + using __adaptor::_RangeAdaptor<_Slide>::operator(); + static constexpr int _S_arity = 2; + static constexpr bool _S_has_simple_extra_args = true; + }; + + inline constexpr _Slide slide; + } + #endif // C++23 } // namespace ranges diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/slide/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/slide/1.cc new file mode 100644 index 00000000000..98560420810 --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/slide/1.cc @@ -0,0 +1,105 @@ +// { dg-options "-std=gnu++23" } +// { dg-do run { target c++23 } } + +#include +#include +#include +#include +#include + +namespace ranges = std::ranges; +namespace views = std::views; + +constexpr bool +test01() +{ + auto v1 = std::array{1, 2} | views::slide(1); + const auto i0 = v1.begin(), i1 = v1.begin() + 1; + VERIFY( i0 + 1 - 1 == i0 ); + VERIFY( i0 < i1 ); + VERIFY( i1 < v1.end() ); + VERIFY( i1 - i0 == 1 ); + VERIFY( i0 - i1 == -1 ); + VERIFY( v1.end() - i1 == 1 ); + VERIFY( i1 - v1.end() == -1 ); + VERIFY( ranges::equal(std::move(v1) | views::join, (int[]){1, 2}) ); + + int x[] = {1, 2, 3, 4}; + auto v2 = x | views::slide(2); + auto i2 = v2.begin(); + i2 += 2; + i2 -= -1; + VERIFY( i2 == v2.end() ); + VERIFY( ranges::size(v2) == 3 ); + VERIFY( ranges::size(std::as_const(v2)) == 3 ); + VERIFY( ranges::equal(v2, (std::initializer_list[]){{1, 2}, {2, 3}, {3, 4}}, + ranges::equal) ); + + int y[] = {1, 2, 3, 4, 5}; + const auto v3 = y | views::slide(3); + VERIFY( ranges::size(v3) == 3 ); + for (unsigned i = 0; i < ranges::size(x); i++) + { + VERIFY( &v3[i][0] == &y[i] + 0 ); + VERIFY( &v3[i][1] == &y[i] + 1 ); + VERIFY( &v3[i][2] == &y[i] + 2 ); + } + + const auto v5 = y | views::slide(5); + VERIFY( ranges::size(v5) == 1 ); + VERIFY( ranges::equal(v5 | views::join, y) ); + + const auto v6 = y | views::slide(6); + VERIFY( ranges::empty(v6) ); + + return true; +} + +constexpr bool +test02() +{ + using __gnu_test::test_input_range; + using __gnu_test::test_forward_range; + using __gnu_test::test_random_access_range; + + using ty1 = ranges::slide_view>>; + static_assert(ranges::forward_range); + static_assert(!ranges::bidirectional_range); + static_assert(!ranges::sized_range); + + using ty2 = ranges::slide_view>>; + static_assert(ranges::random_access_range); + static_assert(ranges::sized_range); + + return true; +} + +constexpr bool +test03() +{ + auto v = views::iota(0, 4) | views::filter([](auto) { return true; }) | views::slide(2); + using ty = decltype(v); + static_assert(ranges::forward_range); + static_assert(ranges::common_range); + static_assert(!ranges::sized_range); + VERIFY( v.begin() == v.begin() ); + VERIFY( v.begin() != v.end() ); + VERIFY( ranges::next(v.begin(), 3) == v.end() ); + auto it = v.begin(); + ++it; + it++; + VERIFY( ranges::next(it) == v.end() ); + it--; + --it; + VERIFY( it == v.begin() ); + + return true; +} + +int +main() +{ + static_assert(test01()); + static_assert(test02()); + static_assert(test03()); +}