From patchwork Tue Feb 11 05:57:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 106316 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 194D83858403 for ; Tue, 11 Feb 2025 05:59:15 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 194D83858403 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Bz36eXsy 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 23B263858D1E for ; Tue, 11 Feb 2025 05:57:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 23B263858D1E 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 23B263858D1E 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=1739253460; cv=none; b=xVwwZhKdwb5upPsSmHKOotE1LZdNLFD68XBibjvA64LSLbZykD83xrIyxkRhrkZ9lb4/2rY0Cs1CWlU95mRzyE9kEmm14QK7LyrRic9iMxinzdgUKPdRMQzFGlyUK6LjKdMfEgWF+8TYRplf2ynmDjCCYtjIpihOeiY8y50y/AE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1739253460; c=relaxed/simple; bh=GQI5Akzd4SIzQ1Q5QwfdT2kNXphY4t/R0b78eVZlIj0=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=c4HbrEYg6vg01dScp6gx22Zlxkh05ZXmdmG9skUP0Ybqr0nKVDsVl3dV388BvpZyIelP0E4Aki+xnkcQc54IeBrkehn/fOyYzoyZZ2R1vfIgNbRUwWoDOolXWBx4gcV7OvXn9o9nE7+Hf3Q3e42zKl7xsV7mrb1YuipAsWGj43Q= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 23B263858D1E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1739253459; 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=qUDevHEwEdKCpjKFou9Grjtl1hGGIzz04+6kWATslKI=; b=Bz36eXsyWguQBHofUZANRo0KtZ96hw+1d6maBKmTjShrz29FKo0iwy1AB/f2fIk9qAolPP oDkC/Y7gBsXMisxbXGfuI+/GY7L6IPjtSUIL3/FQSy7NQ/0XYp5wFpAtSeFd91g2LyJn7d UO8jfYGU1jlmXe5kfFyc9Gt7OM4WP+I= Received: from mail-qv1-f72.google.com (mail-qv1-f72.google.com [209.85.219.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-322-cUW-BpnWP0KVhUjW8UOW1w-1; Tue, 11 Feb 2025 00:57:38 -0500 X-MC-Unique: cUW-BpnWP0KVhUjW8UOW1w-1 X-Mimecast-MFC-AGG-ID: cUW-BpnWP0KVhUjW8UOW1w Received: by mail-qv1-f72.google.com with SMTP id 6a1803df08f44-6e44a0bfc3eso4134546d6.3 for ; Mon, 10 Feb 2025 21:57:38 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739253458; x=1739858258; 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=qUDevHEwEdKCpjKFou9Grjtl1hGGIzz04+6kWATslKI=; b=I+5FThZA0AbvEcknf/O/IS9Xm3TbMIf1OHh951AQTARVZtuJ8Pxpe5t9UdKb3x2Nom V72mo1nxDIn/oRCcP+SWcDJvosMtsHophHITtSI7xOYtQz1rp8rxDNfCxzFeHYrysi1y 7uQayOHo12I5QreGJjdE0ol8Lf3iZx4XtCqR3eXAgEjeeb8mWucTWX3XFHfJ389WldVv +mUYI6ol+pnFUI8T7R62Zji96B27qoPSC0uVJv5o18bb8gF75w7OgM3U3+MoGLon9RO5 A29xeIFo99milt47KD/4XV6DK8YMS86TGyBJgaD/dnXG6Xyj2k0/6sO6cenLWHCF6Qag RqTA== X-Gm-Message-State: AOJu0YyoZvG58dQcpI760oGBEzkTYCnn/kVPBTVPmK/ARHhrX0XzZ22H 1w3uf7bFpoyczHH7ULziYlXx/bjNtVHi+zzO9GEzJV8Itnpk+/D5J4eWkrEAqRaSDhx9BPuKAhi nrr4VaPdT75FN5x+AdxmDpSGMforQi6/OJD+e9tseksbeo+rKXX5V728nWyoLgy1dYAKEJFBRts 9zQjy1l8OxkU87o9x141S/gnuk3PCnShyQnKOz X-Gm-Gg: ASbGncuEXAGzRbBil5DVvBgl8ZLqJKGoNF7Eri+QjyrsCIQ5Gx0KPlV/mftsGdU5RDr hu66L0JgcaIGWJm6TRVcC7eI12VVCqrTJGg3JKv6imJ729ZzAz7/9pBTIkNrecA7uJVq9sLT/q1 xOkCrui6gUdRCZWPxKAp05IPqpgBXh0iNXX+6M/u/G9jjtF8U2zmbdzl/+y+LTzpph6qJU6790j RfbzFmn60Ir8dHhGktPgYraLIl0qIO1iclmoMpaU9+BFDFaKJM1lUHrV/2JxKqJZNDQKxxiGJL+ qRXhrSWRjgWxRPNsxDp0GB6TSLREU0zOhvuOxZjw3vrA X-Received: by 2002:a05:620a:319f:b0:7b8:5629:5d58 with SMTP id af79cd13be357-7c069cf1bb6mr65844385a.4.1739253457550; Mon, 10 Feb 2025 21:57:37 -0800 (PST) X-Google-Smtp-Source: AGHT+IH9yPWz4PrRw0T1upCAKBvtXmjDAprWUtbWcGQ451lcfTmTMjsYmsMfmNqLEf0oQf64DtNPKg== X-Received: by 2002:a05:620a:319f:b0:7b8:5629:5d58 with SMTP id af79cd13be357-7c069cf1bb6mr65843485a.4.1739253457100; Mon, 10 Feb 2025 21:57:37 -0800 (PST) Received: from localhost.localdomain (ool-18bb2a2e.dyn.optonline.net. [24.187.42.46]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-6e43e6b3c32sm54209346d6.124.2025.02.10.21.57.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Feb 2025 21:57:36 -0800 (PST) From: Patrick Palka To: gcc-patches@gcc.gnu.org Cc: libstdc++@gcc.gnu.org, Patrick Palka Subject: [PATCH] libstdc++: Implement P3138R5 views::cache_latest Date: Tue, 11 Feb 2025 00:57:34 -0500 Message-ID: <20250211055734.2852490-1-ppalka@redhat.com> X-Mailer: git-send-email 2.48.1.291.g388218fac7.dirty MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: kdRDDK1EpPIglRZSZn0zTbbmUAyGPOvLQ7VMktUm08Q_1739253458 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true 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_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP 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.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org Tested on x86_64-pc-linux-gnu, does this look OK for trunk? -- >8 -- libstdc++-v3/ChangeLog: * include/bits/version.def (ranges_cache_latest): Define. * include/bits/version.h: Regenerate. * include/std/ranges (cache_latest_view): Define for C++26. (cache_latest_view::_Iterator): Likewise. (cache_latest_view::_Sentinel): Likewise. (views::__detail::__can_cache_latest): Likewise. (views::_CacheLatest, views::cache_latest): Likewise. * testsuite/std/ranges/adaptors/cache_latest/1.cc: New test. --- libstdc++-v3/include/bits/version.def | 8 ++ libstdc++-v3/include/bits/version.h | 10 ++ libstdc++-v3/include/std/ranges | 189 ++++++++++++++++++++++++++ 3 files changed, 207 insertions(+) diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 002e560dc0d..6fb5db2e1fc 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -1837,6 +1837,14 @@ ftms = { }; }; +ftms = { + name = ranges_cache_latest; + values = { + v = 202411; + cxxmin = 26; + }; +}; + ftms = { name = ranges_concat; values = { diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 70de189b1e0..db61a396c45 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -2035,6 +2035,16 @@ #endif /* !defined(__cpp_lib_is_virtual_base_of) && defined(__glibcxx_want_is_virtual_base_of) */ #undef __glibcxx_want_is_virtual_base_of +#if !defined(__cpp_lib_ranges_cache_latest) +# if (__cplusplus > 202302L) +# define __glibcxx_ranges_cache_latest 202411L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_cache_latest) +# define __cpp_lib_ranges_cache_latest 202411L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_cache_latest) && defined(__glibcxx_want_ranges_cache_latest) */ +#undef __glibcxx_want_ranges_cache_latest + #if !defined(__cpp_lib_ranges_concat) # if (__cplusplus > 202302L) # define __glibcxx_ranges_concat 202403L diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 5c795a90fbc..db9a00be264 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -58,6 +58,7 @@ #define __glibcxx_want_ranges_as_const #define __glibcxx_want_ranges_as_rvalue #define __glibcxx_want_ranges_cartesian_product +#define __glibcxx_want_ranges_cache_latest #define __glibcxx_want_ranges_concat #define __glibcxx_want_ranges_chunk #define __glibcxx_want_ranges_chunk_by @@ -1534,6 +1535,8 @@ namespace views::__adaptor this->_M_payload._M_apply(_Optional_func{__f}, __i); return this->_M_get(); } + + using _Optional_base<_Tp>::_M_reset; }; template @@ -10203,6 +10206,192 @@ namespace ranges } // namespace ranges #endif // __cpp_lib_ranges_concat +#if __cpp_lib_ranges_cache_latest // C++ >= 26 +namespace ranges +{ + template + requires view<_Vp> + class cache_latest_view : public view_interface> + { + _Vp _M_base = _Vp(); + + using __cache_t = conditional_t>, + add_pointer_t>, + range_reference_t<_Vp>>; + __detail::__non_propagating_cache<__cache_t> _M_cache; + + class _Iterator; + class _Sentinel; + + public: + cache_latest_view() requires default_initializable<_Vp> = default; + + constexpr explicit + cache_latest_view(_Vp __base) + : _M_base(std::move(__base)) + { } + + constexpr _Vp + base() const & requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() + { return _Iterator(*this); } + + constexpr auto + end() + { return _Sentinel(*this); } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + }; + + template + cache_latest_view(_Range&&) -> cache_latest_view>; + + template + requires view<_Vp> + class cache_latest_view<_Vp>::_Iterator + { + cache_latest_view* _M_parent; + iterator_t<_Vp> _M_current; + + constexpr explicit + _Iterator(cache_latest_view& __parent) + : _M_parent(std::__addressof(__parent)), + _M_current(ranges::begin(__parent._M_base)) + { } + + friend class cache_latest_view; + + public: + using difference_type = range_difference_t<_Vp>; + using value_type = range_value_t<_Vp>; + using iterator_concept = input_iterator_tag; + + _Iterator(_Iterator&&) = default; + + _Iterator& + operator=(_Iterator&&) = default; + + constexpr iterator_t<_Vp> + base() && + { return std::move(_M_current); } + + constexpr const iterator_t<_Vp>& + base() const & noexcept + { return _M_current; } + + constexpr range_reference_t<_Vp>& + operator*() const + { + if constexpr (is_reference_v>) + { + if (!_M_parent->_M_cache) + _M_parent->_M_cache = std::__addressof(__detail::__as_lvalue(*_M_current)); + return **_M_parent->_M_cache; + } + else + { + if (!_M_parent->_M_cache) + _M_parent->_M_cache._M_emplace_deref(_M_current); + return *_M_parent->_M_cache; + } + } + + constexpr _Iterator& + operator++() + { + _M_parent->_M_cache._M_reset(); + ++_M_current; + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + friend constexpr range_rvalue_reference_t<_Vp> + iter_move(const _Iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_current))) + { return ranges::iter_move(__i._M_current); } + + friend constexpr void + iter_swap(const _Iterator& __x, const _Iterator& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) + requires indirectly_swappable> + { ranges::iter_swap(__x._M_current, __y._M_current); } + }; + + template + requires view<_Vp> + class cache_latest_view<_Vp>::_Sentinel + { + sentinel_t<_Vp> _M_end = sentinel_t<_Vp>(); + + constexpr explicit + _Sentinel(cache_latest_view& parent) + : _M_end(ranges::end(parent._M_base)) + { } + + friend class cache_latest_view; + + public: + _Sentinel() = default; + + constexpr sentinel_t<_Vp> + base() const + { return _M_end; } + + friend constexpr bool + operator==(const _Iterator& __x, const _Sentinel& __y) + { return __x._M_current == __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_current - __y._M_end; } + + friend constexpr range_difference_t<_Vp> + operator-(const _Sentinel& __x, const _Iterator& __y) + requires sized_sentinel_for, iterator_t<_Vp>> + { return __x._M_end - __y._M_current; } + }; + + namespace views + { + namespace __detail + { + template + concept __can_cache_latest = requires { cache_latest_view(std::declval<_Tp>()); }; + } + + struct _CacheLatest : __adaptor::_RangeAdaptorClosure<_CacheLatest> + { + template + requires __detail::__can_cache_latest<_Range> + constexpr auto + operator() [[nodiscard]] (_Range&& __r) const + { return cache_latest_view(std::forward<_Range>(__r)); } + + static constexpr bool _S_has_simple_call_op = true; + }; + + inline constexpr _CacheLatest cache_latest; + } +} // namespace ranges +#endif // __cpp_lib_ranges_cache_latest + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // library concepts