From patchwork Tue Oct 19 14:35:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 46400 X-Patchwork-Delegate: jwakely.gcc@gmail.com 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 008BD3857C40 for ; Tue, 19 Oct 2021 14:36:29 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 008BD3857C40 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1634654190; bh=cqk3iqTk+A4KwTtQHRWUBe8X1cdbhFwWAdlY2aLv8aA=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=nRHHmizj6DbiYZhheCQU3/bZnnIiX6unwr3iWs/qgjLs59TdcOxFFhySSjo8yBStz pdfFkv9EiLmPWoKgkouZObOHqvfOkz2uJdZnbymR0HEHGHvcSyYHgTk5FD+BZE9jQ6 cRdXAJqUe29oUTtyGD2QfNAn9S2DDyKi/FlmVmsg= 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 DF2CD3858414 for ; Tue, 19 Oct 2021 14:35:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org DF2CD3858414 Received: from mail-qt1-f200.google.com (mail-qt1-f200.google.com [209.85.160.200]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-1-Cc8kuuH3OaOc7Jw7-OJkxQ-1; Tue, 19 Oct 2021 10:35:26 -0400 X-MC-Unique: Cc8kuuH3OaOc7Jw7-OJkxQ-1 Received: by mail-qt1-f200.google.com with SMTP id 103-20020aed2170000000b002a79b815862so73089qtc.11 for ; Tue, 19 Oct 2021 07:35:26 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=cqk3iqTk+A4KwTtQHRWUBe8X1cdbhFwWAdlY2aLv8aA=; b=SfnFYCL9eVe3Mly522KjdRLS36LrJnU5lhO/3jd94L6Es4ALxYQOZFRJyOg/3g5tGj WF/dvZImZl/d4+owSjJxCeE/5gOCFi7RFA1XejCl3fCTlsb9aksO+NlQLHDM51V0HOZM qeaBbLFeFI7syFdl3lrBdHfes57L+Ey+hqOBvJThcslU4wktOj3HR0qewy+lHDfBvydB mlk/GhR5xGHlQgIEceJzhhKgXqEDbB4gq7hXhOuU4bS7y4Mo3HL5HowKAanUr8+GKa4o ZkzXd6YAWOUQNIHCgLGnI1QGeTA4BFEgKsVX6W0BWKdPstAwxXEyWB1T2EfNosDeKAOv iNVw== X-Gm-Message-State: AOAM5338DFk4Tlwkkb/t99Ry2nNBWtQMrF1NmHfh1+rpJHVDyiU4Wbkg mMF0/xF9qhgtYBATGQVQTJclm1IZWzB18+5RY4NdDqUgK/lVMtWePsvuoKTsZlXhtdMD8wgdNGz RpG913w2zpnERqMweamhV+zAXtQ/02wuIQFKaJcdJJyfUJns6aiR35QO0/Nv/s/rbllQ= X-Received: by 2002:ac8:5984:: with SMTP id e4mr288322qte.235.1634654125311; Tue, 19 Oct 2021 07:35:25 -0700 (PDT) X-Google-Smtp-Source: ABdhPJy5l4LYEZBjIi2CoRl3HBNrVC6A1N6RrGduDhn3WQulNAOvYAL+F3OBNM7zcOrmac6gZdrEoA== X-Received: by 2002:ac8:5984:: with SMTP id e4mr288262qte.235.1634654124834; Tue, 19 Oct 2021 07:35:24 -0700 (PDT) Received: from localhost.localdomain (ool-457d493a.dyn.optonline.net. [69.125.73.58]) by smtp.gmail.com with ESMTPSA id s12sm7970255qkg.22.2021.10.19.07.35.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Oct 2021 07:35:24 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [PATCH] libstdc++: Implement LWG 3549 changes to ranges::enable_view Date: Tue, 19 Oct 2021 10:35:21 -0400 Message-Id: <20211019143521.1572302-1-ppalka@redhat.com> X-Mailer: git-send-email 2.33.1.711.g9d530dc002 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-15.1 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, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_FILL_THIS_FORM_SHORT autolearn=unavailable autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" This patch also reverts the r11-3504 workaround since it's made obsolete by this resolution. Tested on x86_64-pc-linux-gnu, does this look OK for trunk only? libstdc++-v3/ChangeLog: * include/bits/ranges_base.h (view_interface): Forward declare. (__detail::__is_derived_from_view_interface_fn): Declare (__detail::__is_derived_from_view_interface): Define as per LWG 3549. (enable_view): Adjust as per LWG 3549. * include/bits/ranges_util.h (view_interface): Don't derive from view_base. * include/std/ranges (filter_view): Revert r11-3504 change. (transform_view): Likewise. (take_view): Likewise. (take_while_view): Likewise. (drop_view): Likewise. (drop_while_view): Likewise. (join_view): Likewise. (split_view): Likewise. (reverse_view): Likewise. * testsuite/std/ranges/adaptors/sizeof.cc: Update expected sizes. * testsuite/std/ranges/view.cc (test_view::test_view): Remove now that views no longer need to be default-initializable. (test01): New test. --- libstdc++-v3/include/bits/ranges_base.h | 21 ++++++++- libstdc++-v3/include/bits/ranges_util.h | 2 +- libstdc++-v3/include/std/ranges | 45 +++++++++---------- .../testsuite/std/ranges/adaptors/sizeof.cc | 6 +-- libstdc++-v3/testsuite/std/ranges/view.cc | 28 ++++++++++-- 5 files changed, 70 insertions(+), 32 deletions(-) diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index 01d0c35f4b4..7801b2fd023 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -614,12 +614,31 @@ namespace ranges template using range_size_t = decltype(ranges::size(std::declval<_Range&>())); + template + requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>> + class view_interface; // defined in + + namespace __detail + { + template + requires (!same_as<_Tp, view_interface<_Up>>) + void __is_derived_from_view_interface_fn(const _Tp&, + const view_interface<_Up>&); // not defined + + // Returns true iff _Tp has exactly one public base class that's a + // specialization of view_interface. + template + concept __is_derived_from_view_interface + = requires (_Tp __t) { __is_derived_from_view_interface_fn(__t, __t); }; + } + /// [range.view] The ranges::view_base type. struct view_base { }; /// [range.view] The ranges::enable_view boolean. template - inline constexpr bool enable_view = derived_from<_Tp, view_base>; + inline constexpr bool enable_view = derived_from<_Tp, view_base> + || __detail::__is_derived_from_view_interface<_Tp>; /// [range.view] The ranges::view concept. template diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h index 1afa66d298c..5c0bef26220 100644 --- a/libstdc++-v3/include/bits/ranges_util.h +++ b/libstdc++-v3/include/bits/ranges_util.h @@ -61,7 +61,7 @@ namespace ranges /// The ranges::view_interface class template template requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>> - class view_interface : public view_base + class view_interface { private: constexpr _Derived& _M_derived() noexcept diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 64396027c1b..e47fc075bbe 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -1533,9 +1533,9 @@ namespace views::__adaptor { return __y.__equal(__x); } }; + _Vp _M_base = _Vp(); [[no_unique_address]] __detail::__box<_Pred> _M_pred; [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin; - _Vp _M_base = _Vp(); public: filter_view() requires (default_initializable<_Vp> @@ -1544,7 +1544,7 @@ namespace views::__adaptor constexpr filter_view(_Vp __base, _Pred __pred) - : _M_pred(std::move(__pred)), _M_base(std::move(__base)) + : _M_base(std::move(__base)), _M_pred(std::move(__pred)) { } constexpr _Vp @@ -1900,8 +1900,8 @@ namespace views::__adaptor friend _Sentinel; }; - [[no_unique_address]] __detail::__box<_Fp> _M_fun; _Vp _M_base = _Vp(); + [[no_unique_address]] __detail::__box<_Fp> _M_fun; public: transform_view() requires (default_initializable<_Vp> @@ -1910,7 +1910,7 @@ namespace views::__adaptor constexpr transform_view(_Vp __base, _Fp __fun) - : _M_fun(std::move(__fun)), _M_base(std::move(__base)) + : _M_base(std::move(__base)), _M_fun(std::move(__fun)) { } constexpr _Vp @@ -2037,15 +2037,15 @@ namespace views::__adaptor friend _Sentinel; }; - range_difference_t<_Vp> _M_count = 0; _Vp _M_base = _Vp(); + range_difference_t<_Vp> _M_count = 0; public: take_view() requires default_initializable<_Vp> = default; constexpr take_view(_Vp base, range_difference_t<_Vp> __count) - : _M_count(std::move(__count)), _M_base(std::move(base)) + : _M_base(std::move(base)), _M_count(std::move(__count)) { } constexpr _Vp @@ -2268,8 +2268,8 @@ namespace views::__adaptor friend _Sentinel; }; - [[no_unique_address]] __detail::__box<_Pred> _M_pred; _Vp _M_base = _Vp(); + [[no_unique_address]] __detail::__box<_Pred> _M_pred; public: take_while_view() requires (default_initializable<_Vp> @@ -2278,7 +2278,7 @@ namespace views::__adaptor constexpr take_while_view(_Vp base, _Pred __pred) - : _M_pred(std::move(__pred)), _M_base(std::move(base)) + : _M_base(std::move(base)), _M_pred(std::move(__pred)) { } constexpr _Vp @@ -2349,8 +2349,8 @@ namespace views::__adaptor class drop_view : public view_interface> { private: - range_difference_t<_Vp> _M_count = 0; _Vp _M_base = _Vp(); + range_difference_t<_Vp> _M_count = 0; // ranges::next(begin(base), count, end(base)) is O(1) if _Vp satisfies // both random_access_range and sized_range. Otherwise, cache its result. @@ -2366,7 +2366,7 @@ namespace views::__adaptor constexpr drop_view(_Vp __base, range_difference_t<_Vp> __count) - : _M_count(__count), _M_base(std::move(__base)) + : _M_base(std::move(__base)), _M_count(__count) { __glibcxx_assert(__count >= 0); } constexpr _Vp @@ -2503,9 +2503,9 @@ namespace views::__adaptor class drop_while_view : public view_interface> { private: + _Vp _M_base = _Vp(); [[no_unique_address]] __detail::__box<_Pred> _M_pred; [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin; - _Vp _M_base = _Vp(); public: drop_while_view() requires (default_initializable<_Vp> @@ -2514,7 +2514,7 @@ namespace views::__adaptor constexpr drop_while_view(_Vp __base, _Pred __pred) - : _M_pred(std::move(__pred)), _M_base(std::move(__base)) + : _M_base(std::move(__base)), _M_pred(std::move(__pred)) { } constexpr _Vp @@ -2850,9 +2850,9 @@ namespace views::__adaptor friend _Sentinel; }; + _Vp _M_base = _Vp(); [[no_unique_address]] __detail::__non_propagating_cache> _M_inner; - _Vp _M_base = _Vp(); public: join_view() requires default_initializable<_Vp> = default; @@ -3288,12 +3288,12 @@ namespace views::__adaptor { ranges::iter_swap(__x._M_i_current(), __y._M_i_current()); } }; + _Vp _M_base = _Vp(); _Pattern _M_pattern = _Pattern(); // XXX: _M_current is "present only if !forward_range" [[no_unique_address]] __detail::__maybe_present_t, __detail::__non_propagating_cache>> _M_current; - _Vp _M_base = _Vp(); public: @@ -3303,7 +3303,7 @@ namespace views::__adaptor constexpr lazy_split_view(_Vp __base, _Pattern __pattern) - : _M_pattern(std::move(__pattern)), _M_base(std::move(__base)) + : _M_base(std::move(__base)), _M_pattern(std::move(__pattern)) { } template @@ -3311,8 +3311,8 @@ namespace views::__adaptor && constructible_from<_Pattern, single_view>> constexpr lazy_split_view(_Range&& __r, range_value_t<_Range> __e) - : _M_pattern(views::single(std::move(__e))), - _M_base(views::all(std::forward<_Range>(__r))) + : _M_base(views::all(std::forward<_Range>(__r))), + _M_pattern(views::single(std::move(__e))) { } constexpr _Vp @@ -3410,9 +3410,9 @@ namespace views::__adaptor class split_view : public view_interface> { private: + _Vp _M_base = _Vp(); _Pattern _M_pattern = _Pattern(); __detail::__non_propagating_cache>> _M_cached_begin; - _Vp _M_base = _Vp(); struct _Iterator; struct _Sentinel; @@ -3424,8 +3424,7 @@ namespace views::__adaptor constexpr split_view(_Vp __base, _Pattern __pattern) - : _M_pattern(std::move(__pattern)), - _M_base(std::move(__base)) + : _M_base(std::move(__base)), _M_pattern(std::move(__pattern)) { } template @@ -3433,8 +3432,8 @@ namespace views::__adaptor && constructible_from<_Pattern, single_view>> constexpr split_view(_Range&& __r, range_value_t<_Range> __e) - : _M_pattern(views::single(std::move(__e))), - _M_base(views::all(std::forward<_Range>(__r))) + : _M_base(views::all(std::forward<_Range>(__r))), + _M_pattern(views::single(std::move(__e))) { } constexpr _Vp @@ -3759,11 +3758,11 @@ namespace views::__adaptor && sized_sentinel_for, iterator_t<_Vp>>); + _Vp _M_base = _Vp(); [[no_unique_address]] __detail::__maybe_present_t<_S_needs_cached_begin, __detail::_CachedPosition<_Vp>> _M_cached_begin; - _Vp _M_base = _Vp(); public: reverse_view() requires default_initializable<_Vp> = default; diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc index 219e2a61f07..61524d4c0ad 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc @@ -42,11 +42,11 @@ static_assert(sizeof(ranges::drop_while_view) == 4*ptr); static_assert(sizeof(ranges::transform_view) == 3*ptr); static_assert(sizeof(ranges::filter_view) == 3*ptr); -static_assert(sizeof(ranges::take_while_view) == 3*ptr); +static_assert(sizeof(ranges::take_while_view) == 2*ptr); static_assert(sizeof(ranges::drop_while_view) == 3*ptr); -static_assert(sizeof(ranges::transform_view) == 3*ptr); +static_assert(sizeof(ranges::transform_view) == 2*ptr); static_assert(sizeof(ranges::lazy_split_view) == 4*ptr); static_assert - (sizeof(ranges::reverse_view>) == 4*ptr); + (sizeof(ranges::reverse_view>) == 3*ptr); diff --git a/libstdc++-v3/testsuite/std/ranges/view.cc b/libstdc++-v3/testsuite/std/ranges/view.cc index dd8258220ed..98a162ec866 100644 --- a/libstdc++-v3/testsuite/std/ranges/view.cc +++ b/libstdc++-v3/testsuite/std/ranges/view.cc @@ -52,10 +52,7 @@ static_assert(!std::ranges::view<__gnu_test::test_random_access_range>); template struct test_view : __gnu_test::test_random_access_range, std::ranges::view_base -{ - // views must be default-initializable: - test_view() : __gnu_test::test_random_access_range(nullptr, nullptr) { } -}; +{ }; static_assert(std::ranges::view>); @@ -63,3 +60,26 @@ template<> constexpr bool std::ranges::enable_view> = false; static_assert(!std::ranges::view>); + +void +test01() +{ + // Verify LWG 3549 changes to ranges::enable_view. + using std::ranges::view_interface; + + struct v1 + : __gnu_test::test_random_access_range, view_interface { }; + static_assert(!std::derived_from); + static_assert(std::ranges::enable_view); + + struct v2 : v1, view_interface { }; + static_assert(!std::derived_from); + static_assert(!std::ranges::enable_view); + + struct v3 : __gnu_test::test_random_access_range { }; + static_assert(!std::derived_from); + static_assert(!std::ranges::enable_view); + + struct v4 { }; + static_assert(!std::ranges::enable_view>); +}