From patchwork Mon Feb 17 22:00:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 1239623 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-519677-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha1 header.s=default header.b=q4/qmdvO; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=bZqbhCc4; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48Lyds56R8z9sRG for ; Tue, 18 Feb 2020 09:02:41 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:mime-version:content-type :content-transfer-encoding; q=dns; s=default; b=MX2wgEElHHFodJny T2sFeuC/E28BG6mdhjXWdh0pjKwYyaW8Z4698xT4Rj9OjhbiSqcMzdmhcCfmMVB5 PArj48zc3VjaENinluY7oCFd4KtDdcoO0XL+XO4QNcVAEdIuHgNyBcuvO/zGl8Go kppvqOmtS+3t5p1Mf1pchYjmBuo= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:mime-version:content-type :content-transfer-encoding; s=default; bh=AZOnr9Po4nN0HvDwNX5U7C g60Jc=; b=q4/qmdvOnqfyTVaYciOsvdAWV8vVXnM2LNkdyhEnAp3c/QAavbosKi FBlP/scTWprOpqubcfQb26+1GyNPnwCta95dzMGuM5gEXyyK+K1+EQMktSuk54i9 xQyZBt9lu6bfziY16A1PH7hGOKUVOTlfeaW5SJJQ1hdy9D31Nd4aQ= Received: (qmail 1760 invoked by alias); 17 Feb 2020 22:02:07 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 1643 invoked by uid 89); 17 Feb 2020 22:02:06 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.4 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE autolearn=unavailable version=3.3.1 spammy=Forwarding X-HELO: us-smtp-1.mimecast.com Received: from us-smtp-delivery-1.mimecast.com (HELO us-smtp-1.mimecast.com) (205.139.110.120) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 17 Feb 2020 22:02:04 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1581976922; 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=UFG9achsOvjqr7MIllTfg0CV+DYKCqRSjKd8FCSmf8w=; b=bZqbhCc4z4RB08ff1FRfiN7zmqnGa023nUc1qeEcMKkKMPwkHlF+z1gQt7uBTkdH/kOZO1 8RMI3yg9PT2qDT4qPpFHCn2jiXvNdQNDzeWFqMiRtSVdElEtU4MK1cTAThChjpv1/9Ht/R mUuiokCs5elUJSAqkL9NUV2RtdXJkyQ= Received: from mail-qt1-f197.google.com (mail-qt1-f197.google.com [209.85.160.197]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-80-xIL6aYPjOuOZvR_7gLYSOQ-1; Mon, 17 Feb 2020 17:01:57 -0500 Received: by mail-qt1-f197.google.com with SMTP id c8so11746901qte.22 for ; Mon, 17 Feb 2020 14:01:56 -0800 (PST) Received: from localhost.localdomain (ool-457d493a.dyn.optonline.net. [69.125.73.58]) by smtp.gmail.com with ESMTPSA id y91sm889331qtd.13.2020.02.17.14.01.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Feb 2020 14:01:55 -0800 (PST) From: Patrick Palka To: gcc-patches@gcc.gnu.org Cc: libstdc++@gcc.gnu.org, jwakely@redhat.com, Patrick Palka Subject: [PATCH 1/2] libstdc++: P1243R4 Rangify new algorithms Date: Mon, 17 Feb 2020 17:00:58 -0500 Message-Id: <20200217220059.1047256-1-ppalka@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-IsSubscribed: yes This adds rangified overloads for for_each_n, sample and clamp as per P1243R4. libstdc++-v3/ChangeLog: P1243R4 * include/bits/ranges_algo.h (for_each_n_result, __for_each_n_fn, for_each_n, __sample_fn, sample, __clamp_fn, clamp): New. * testsuite/25_algorithms/clamp/constrained.cc: New test. * testsuite/25_algorithms/for_each/constrained.cc: Augment test. * testsuite/25_algorithms/sample/constrained.cc: New test. --- libstdc++-v3/include/bits/ranges_algo.h | 115 ++++++++++++++++++ .../25_algorithms/clamp/constrained.cc | 58 +++++++++ .../25_algorithms/for_each/constrained.cc | 44 +++++++ .../25_algorithms/sample/constrained.cc | 68 +++++++++++ 4 files changed, 285 insertions(+) create mode 100644 libstdc++-v3/testsuite/25_algorithms/clamp/constrained.cc create mode 100644 libstdc++-v3/testsuite/25_algorithms/sample/constrained.cc diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h index 83f295722e9..c50b369c6c0 100644 --- a/libstdc++-v3/include/bits/ranges_algo.h +++ b/libstdc++-v3/include/bits/ranges_algo.h @@ -195,6 +195,39 @@ namespace ranges inline constexpr __for_each_fn for_each{}; + template + using for_each_n_result = for_each_result<_Iter, _Fp>; + + struct __for_each_n_fn + { + template> _Fun> + constexpr for_each_n_result<_Iter, _Fun> + operator()(_Iter __first, iter_difference_t<_Iter> __n, + _Fun __f, _Proj __proj = {}) const + { + if constexpr (random_access_iterator<_Iter>) + { + if (__n <= 0) + return {std::move(__first), std::move(__f)}; + auto __last = __first + __n; + return ranges::for_each(std::move(__first), std::move(__last), + std::move(__f), std::move(__proj)); + } + else + { + while (__n-- > 0) + { + std::__invoke(__f, std::__invoke(__proj, *__first)); + ++__first; + } + return {std::move(__first), std::move(__f)}; + } + } + }; + + inline constexpr __for_each_n_fn for_each_n{}; + struct __find_fn { template _Sent, typename _Tp, @@ -1694,6 +1727,64 @@ namespace ranges inline constexpr __rotate_copy_fn rotate_copy{}; + struct __sample_fn + { + template _Sent, + weakly_incrementable _Out, typename _Gen> + requires (forward_iterator<_Iter> || random_access_iterator<_Out>) + && indirectly_copyable<_Iter, _Out> + && uniform_random_bit_generator> + _Out + operator()(_Iter __first, _Sent __last, _Out __out, + iter_difference_t<_Iter> __n, _Gen&& __g) const + { + if constexpr (forward_iterator<_Iter>) + { + // FIXME: Forwarding to std::sample here requires computing __lasti + // which may take linear time. + auto __lasti = ranges::next(__first, __last); + return std::sample(std::move(__first), std::move(__lasti), + std::move(__out), __n, std::forward<_Gen>(__g)); + } + else + { + using __distrib_type + = uniform_int_distribution>; + using __param_type = typename __distrib_type::param_type; + __distrib_type __d{}; + iter_difference_t<_Iter> __sample_sz = 0; + while (__first != __last && __sample_sz != __n) + { + __out[__sample_sz++] = *__first; + ++__first; + } + for (auto __pop_sz = __sample_sz; __first != __last; + ++__first, (void) ++__pop_sz) + { + const auto __k = __d(__g, __param_type{0, __pop_sz}); + if (__k < __n) + __out[__k] = *__first; + } + return __out + __sample_sz; + } + } + + template + requires (forward_range<_Range> || random_access_iterator<_Out>) + && indirectly_copyable, _Out> + && uniform_random_bit_generator> + _Out + operator()(_Range&& __r, _Out __out, + range_difference_t<_Range> __n, _Gen&& __g) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__out), __n, + std::forward<_Gen>(__g)); + } + }; + + inline constexpr __sample_fn sample{}; + #ifdef _GLIBCXX_USE_C99_STDINT_TR1 struct __shuffle_fn { @@ -3102,6 +3193,30 @@ namespace ranges inline constexpr __max_fn max{}; + struct __clamp_fn + { + template> _Comp + = ranges::less> + constexpr const _Tp& + operator()(const _Tp& __val, const _Tp& __lo, const _Tp& __hi, + _Comp __comp = {}, _Proj __proj = {}) const + { + __glibcxx_assert(!(std::__invoke(__comp, + std::__invoke(__proj, __hi), + std::__invoke(__proj, __lo)))); + auto&& __proj_val = std::__invoke(__proj, __val); + if (std::__invoke(__comp, __proj_val, std::__invoke(__proj, __lo))) + return __lo; + else if (std::__invoke(__comp, std::__invoke(__proj, __hi), __proj_val)) + return __hi; + else + return __val; + } + }; + + inline constexpr __clamp_fn clamp{}; + template struct minmax_result { diff --git a/libstdc++-v3/testsuite/25_algorithms/clamp/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/clamp/constrained.cc new file mode 100644 index 00000000000..1964bb60354 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/clamp/constrained.cc @@ -0,0 +1,58 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i, j; +}; + +void +test01() +{ + VERIFY( ranges::clamp(1, 2, 4) == 2 ); + VERIFY( ranges::clamp(3, 2, 4) == 3 ); + VERIFY( ranges::clamp(5, 2, 4) == 4 ); + + VERIFY( ranges::clamp(1, 4, 2, ranges::greater{}) == 2 ); + VERIFY( ranges::clamp(3, 4, 2, ranges::greater{}) == 3 ); + VERIFY( ranges::clamp(5, 4, 2, ranges::greater{}) == 4 ); + + VERIFY( ranges::clamp(1, 2, 4, ranges::greater{}, std::negate<>{}) == 2 ); + VERIFY( ranges::clamp(3, 2, 4, ranges::greater{}, std::negate<>{}) == 3 ); + VERIFY( ranges::clamp(5, 2, 4, ranges::greater{}, std::negate<>{}) == 4 ); + + static_assert(ranges::clamp(X{1,2}, X{1,3}, X{1,4}, {}, &X::i).j == 2); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/for_each/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/for_each/constrained.cc index 142ad2e57da..31ca0a7046a 100644 --- a/libstdc++-v3/testsuite/25_algorithms/for_each/constrained.cc +++ b/libstdc++-v3/testsuite/25_algorithms/for_each/constrained.cc @@ -26,6 +26,7 @@ using __gnu_test::test_container; using __gnu_test::test_range; using __gnu_test::input_iterator_wrapper; using __gnu_test::forward_iterator_wrapper; +using __gnu_test::random_access_iterator_wrapper; namespace ranges = std::ranges; @@ -75,9 +76,52 @@ test02() static_assert(f() == 6); } +template typename wrapper> +void +test03() +{ + int x[] = {1,2,3,4,5}; + test_range rx(x); + int s = 0; + auto func = [&s](int i){ s += i; }; + auto [i,f] = ranges::for_each_n(rx.begin(), 3, func); + VERIFY( i.ptr = x+3 ); + VERIFY( s == 1+2+3 ); + f(1); + VERIFY( s == 1+2+3+1 ); + + s = 0; + rx.bounds.first = x; + auto [j,g] = ranges::for_each_n(rx.begin(), -1, func); + VERIFY( j.ptr == x ); + VERIFY( s == 0 ); + g(1); + VERIFY( s == 1 ); + + s = 0; + rx.bounds.first = x; + auto [k,h] = ranges::for_each_n(rx.begin(), 5, func, std::negate<>{}); + VERIFY( k.ptr == x+5 ); + VERIFY( s == -(1+2+3+4+5) ); + h(-6); + VERIFY( s == -(1+2+3+4+5+6) ); +} + +constexpr bool +test04() +{ + int x[] = {1,2,3,4,5}; + int p = 1; + ranges::for_each_n(x+1, 4, [&p](int i){ p*=i; }, [](int i){ return i+1; }); + return p == 3*4*5*6; +} + int main() { test01(); test02(); + test03(); + test03(); + static_assert(test04()); } diff --git a/libstdc++-v3/testsuite/25_algorithms/sample/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/sample/constrained.cc new file mode 100644 index 00000000000..7ed57e8aefc --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/sample/constrained.cc @@ -0,0 +1,68 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } +// { dg-require-cstdint "" } + +#include +#include +#include +#include + +using __gnu_test::test_range; +using __gnu_test::forward_iterator_wrapper; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::random_access_iterator_wrapper; + +namespace ranges = std::ranges; + +std::mt19937 rng; + +template typename in_wrapper, + template typename out_wrapper> +void +test01() +{ + const int x[] = {1,2,3,4,5,6,7,8,9,10}; + test_range rx(x); + int y[10]; + test_range ry(y); + auto out = ranges::sample(rx.begin(), rx.end(), ry.begin(), 20, rng); + VERIFY( out.ptr == y+10 ); + VERIFY( ranges::equal(x, y) ); + + for (int i = 0; i < 100; i++) + { + int z[5] = {0}; + test_range rz(z); + rx.bounds.first = x; + auto out = ranges::sample(rx, rz.begin(), 5, rng); + VERIFY( out.ptr == z+5 ); + ranges::sort(z); + VERIFY( ranges::adjacent_find(z) == out.ptr ); + VERIFY( ranges::includes(x, z) ); + } +} + +int +main() +{ + test01(); + test01(); +} From patchwork Mon Feb 17 22:00:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 1239622 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-519676-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha1 header.s=default header.b=xynsoUwV; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=SXrihR+k; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48LydP2bKtz9sPJ for ; Tue, 18 Feb 2020 09:02:14 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; q=dns; s= default; b=H1Sh5niCnAFKKwOo2778G8W+rBSfZdUslGzT4U4DGNMkSrYCPydnd agVbekyF1EPUMAIvayfoO4N6dlDI1JwE7Abwg7lbq+coJ/Qh8btoGAoSsEZQYy7T qpeqjC5ukZvdAF77RMpQvcOMJGwe5z35XIErlu1jBJ7AQS+tL73mMA= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; s=default; bh=iOOyG7i3DjketK73g41d6NmZpVg=; b=xynsoUwVXE+KvsN+0Zp+sXsGu/Se /YjID6XUilvs8YBE4/z943GcySFaTc2wJUfxdOSySj9klJbq2YBGb/kmZvVzz/kB cWcxF8Resl6Ag58wfeqYTABIcrkFnhN3GnX0UXHk5wvbqyLiYIMAVh3LuwkQ9owu K8V7xUh/5hNuwwA= Received: (qmail 1541 invoked by alias); 17 Feb 2020 22:02:05 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 1525 invoked by uid 89); 17 Feb 2020 22:02:05 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_NUMSUBJECT, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 spammy= X-HELO: us-smtp-delivery-1.mimecast.com Received: from us-smtp-1.mimecast.com (HELO us-smtp-delivery-1.mimecast.com) (205.139.110.61) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 17 Feb 2020 22:02:02 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1581976920; 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: in-reply-to:in-reply-to:references:references; bh=WVoRUEmXhrhqtb9n88kYOYYJEvFYSBvsTQWILqGyBlI=; b=SXrihR+k27l9IogYMkfHj/EG34NieIlQvI5i7dzldUdTtZnNTtvm++RpZ/DdiQw8JRK6y8 hqMBVPiBQaiQ3Ut8PqixrFSNJU/Gzx9eP4B1Q5o58d5yGM/YsY0wikSlr3oGHLQY+nmaCL enohsL8i9CCmCWQlIeoRrBQ5meepbRU= Received: from mail-qk1-f198.google.com (mail-qk1-f198.google.com [209.85.222.198]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-420-daZMoSLRNtKka-7xaIAt8w-1; Mon, 17 Feb 2020 17:01:58 -0500 Received: by mail-qk1-f198.google.com with SMTP id s189so26217qke.5 for ; Mon, 17 Feb 2020 14:01:58 -0800 (PST) Received: from localhost.localdomain (ool-457d493a.dyn.optonline.net. [69.125.73.58]) by smtp.gmail.com with ESMTPSA id y91sm889331qtd.13.2020.02.17.14.01.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Feb 2020 14:01:56 -0800 (PST) From: Patrick Palka To: gcc-patches@gcc.gnu.org Cc: libstdc++@gcc.gnu.org, jwakely@redhat.com, Patrick Palka Subject: [PATCH 2/2] libstdc++: P2106R0 Alternative wording for GB315 and GB316 Date: Mon, 17 Feb 2020 17:00:59 -0500 Message-Id: <20200217220059.1047256-2-ppalka@redhat.com> In-Reply-To: <20200217220059.1047256-1-ppalka@redhat.com> References: <20200217220059.1047256-1-ppalka@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-IsSubscribed: yes libstdc++-v3/ChangeLog: P2106R0 * include/bits/ranges_algo.h (in_fun_result): New. (for_each_result, for_each_n_result): Change into an alias of in_fun_result. (in_in_result): New. (mismatch_result): Change into an alias of in_in_result. (copy_if_result): Change into an alias of in_out_result. (swap_ranges_result): Change into an alias of in_in_result. (unary_transform_result): Change into an alias of in_out_result. (in_in_out_result): New. (binary_transform_result): Change into an alias of in_in_out_result. (replace_copy_result, replace_copy_if_result, remove_copy_if_result, remove_copy_result, unique_copy_result, reverse_copy_result, rotate_copy_result, partial_sort_copy_result): Change into an alias of in_out_result. (in_out_out_result): New. (partition_copy_result, merge_result): Change into an alias of in_out_out_result. (set_union_result, set_intersection_result): Change into an alias of in_in_out_result. (set_difference_result): Change into an alias of in_out_result. (set_symmetric_difference): Change into an alias of in_in_out_result. (min_max_result): New. (minmax_result, minmax_element_result): Change into an alias of min_max_result. (in_found_result): New. (next_permutation_result, prev_permutation_result): Change into an alias of in_found_result. (__next_permutation_fn::operator(), __prev_permutation_fn::operator()): Adjust following changes to next_permutation_result and prev_permutation_result. * include/bits/ranges_algobase.h (in_out_result): New. (copy_result, move_result, move_backward_result, copy_backward_result, copy_n_result): Change into an alias of in_out_result. * include/bits/ranges_uninitialized.h (uninitialized_copy_result, uninitialized_copy_n_result, uninitialized_move_result, uninitialized_move_n_result): Likewise. * testsuite/25_algorithms/next_permutation/constrained.cc: Adjust uses of structured bindings. * testsuite/25_algorithms/prev_permutation/constrained.cc: Likewise. --- libstdc++-v3/include/bits/ranges_algo.h | 137 +++++++++++------- libstdc++-v3/include/bits/ranges_algobase.h | 19 ++- .../include/bits/ranges_uninitialized.h | 8 +- .../next_permutation/constrained.cc | 4 +- .../prev_permutation/constrained.cc | 4 +- 5 files changed, 108 insertions(+), 64 deletions(-) diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h index c50b369c6c0..31b1bf0d448 100644 --- a/libstdc++-v3/include/bits/ranges_algo.h +++ b/libstdc++-v3/include/bits/ranges_algo.h @@ -152,7 +152,7 @@ namespace ranges inline constexpr __none_of_fn none_of{}; template - struct for_each_result + struct in_fun_result { [[no_unique_address]] _Iter in; [[no_unique_address]] _Fp fun; @@ -160,15 +160,20 @@ namespace ranges template requires convertible_to && convertible_to - operator for_each_result<_Iter2, _F2p>() const & + constexpr + operator in_fun_result<_Iter2, _F2p>() const & { return {in, fun}; } template requires convertible_to<_Iter, _Iter2> && convertible_to<_Fp, _F2p> - operator for_each_result<_Iter2, _F2p>() && + constexpr + operator in_fun_result<_Iter2, _F2p>() && { return {std::move(in), std::move(fun)}; } }; + template + using for_each_result = in_fun_result<_Iter, _Fp>; + struct __for_each_fn { template _Sent, @@ -196,7 +201,7 @@ namespace ranges inline constexpr __for_each_fn for_each{}; template - using for_each_n_result = for_each_result<_Iter, _Fp>; + using for_each_n_result = in_fun_result<_Iter, _Fp>; struct __for_each_n_fn { @@ -416,7 +421,7 @@ namespace ranges inline constexpr __count_if_fn count_if{}; template - struct mismatch_result + struct in_in_result { [[no_unique_address]] _Iter1 in1; [[no_unique_address]] _Iter2 in2; @@ -424,16 +429,21 @@ namespace ranges template requires convertible_to && convertible_to - operator mismatch_result<_IIter1, _IIter2>() const & + constexpr + operator in_in_result<_IIter1, _IIter2>() const & { return {in1, in2}; } template requires convertible_to<_Iter1, _IIter1> && convertible_to<_Iter2, _IIter2> - operator mismatch_result<_IIter1, _IIter2>() && + constexpr + operator in_in_result<_IIter1, _IIter2>() && { return {std::move(in1), std::move(in2)}; } }; + template + using mismatch_result = in_in_result<_Iter1, _Iter2>; + struct __mismatch_fn { template _Sent1, @@ -830,7 +840,7 @@ namespace ranges inline constexpr __is_permutation_fn is_permutation{}; template - using copy_if_result = copy_result<_Iter, _Out>; + using copy_if_result = in_out_result<_Iter, _Out>; struct __copy_if_fn { @@ -869,7 +879,7 @@ namespace ranges inline constexpr __copy_if_fn copy_if{}; template - using swap_ranges_result = mismatch_result<_Iter1, _Iter2>; + using swap_ranges_result = in_in_result<_Iter1, _Iter2>; struct __swap_ranges_fn { @@ -900,10 +910,10 @@ namespace ranges inline constexpr __swap_ranges_fn swap_ranges{}; template - using unary_transform_result = copy_result<_Iter, _Out>; + using unary_transform_result = in_out_result<_Iter, _Out>; template - struct binary_transform_result + struct in_in_out_result { [[no_unique_address]] _Iter1 in1; [[no_unique_address]] _Iter2 in2; @@ -913,17 +923,22 @@ namespace ranges requires convertible_to && convertible_to && convertible_to - operator binary_transform_result<_IIter1, _IIter2, _OOut>() const & + constexpr + operator in_in_out_result<_IIter1, _IIter2, _OOut>() const & { return {in1, in2, out}; } template requires convertible_to<_Iter1, _IIter1> && convertible_to<_Iter2, _IIter2> && convertible_to<_Out, _OOut> - operator binary_transform_result<_IIter1, _IIter2, _OOut>() && + constexpr + operator in_in_out_result<_IIter1, _IIter2, _OOut>() && { return {std::move(in1), std::move(in2), std::move(out)}; } }; + template + using binary_transform_result = in_in_out_result<_Iter1, _Iter2, _Out>; + struct __transform_fn { template _Sent, @@ -1065,7 +1080,7 @@ namespace ranges inline constexpr __replace_if_fn replace_if{}; template - using replace_copy_result = copy_result<_Iter, _Out>; + using replace_copy_result = in_out_result<_Iter, _Out>; struct __replace_copy_fn { @@ -1108,7 +1123,7 @@ namespace ranges inline constexpr __replace_copy_fn replace_copy{}; template - using replace_copy_if_result = copy_result<_Iter, _Out>; + using replace_copy_if_result = in_out_result<_Iter, _Out>; struct __replace_copy_if_fn { @@ -1261,7 +1276,7 @@ namespace ranges inline constexpr __remove_fn remove{}; template - using remove_copy_if_result = copy_result<_Iter, _Out>; + using remove_copy_if_result = in_out_result<_Iter, _Out>; struct __remove_copy_if_fn { @@ -1300,7 +1315,7 @@ namespace ranges inline constexpr __remove_copy_if_fn remove_copy_if{}; template - using remove_copy_result = copy_result<_Iter, _Out>; + using remove_copy_result = in_out_result<_Iter, _Out>; struct __remove_copy_fn { @@ -1379,7 +1394,7 @@ namespace ranges inline constexpr __unique_fn unique{}; template - using unique_copy_result = copy_result<_Iter, _Out>; + using unique_copy_result = in_out_result<_Iter, _Out>; struct __unique_copy_fn { @@ -1514,7 +1529,7 @@ namespace ranges inline constexpr __reverse_fn reverse{}; template - using reverse_copy_result = copy_result<_Iter, _Out>; + using reverse_copy_result = in_out_result<_Iter, _Out>; struct __reverse_copy_fn { @@ -1695,7 +1710,7 @@ namespace ranges inline constexpr __rotate_fn rotate{}; template - using rotate_copy_result = copy_result<_Iter, _Out>; + using rotate_copy_result = in_out_result<_Iter, _Out>; struct __rotate_copy_fn { @@ -2093,7 +2108,7 @@ namespace ranges inline constexpr __partial_sort_fn partial_sort{}; template - using partial_sort_copy_result = copy_result<_Iter, _Out>; + using partial_sort_copy_result = in_out_result<_Iter, _Out>; struct __partial_sort_copy_fn { @@ -2580,28 +2595,33 @@ namespace ranges inline constexpr __stable_partition_fn stable_partition{}; - template - struct partition_copy_result + template + struct in_out_out_result { [[no_unique_address]] _Iter in; [[no_unique_address]] _Out1 out1; - [[no_unique_address]] _O2 out2; + [[no_unique_address]] _Out2 out2; template requires convertible_to && convertible_to - && convertible_to - operator partition_copy_result<_IIter, _OOut1, _OOut2>() const & + && convertible_to + constexpr + operator in_out_out_result<_IIter, _OOut1, _OOut2>() const & { return {in, out1, out2}; } template requires convertible_to<_Iter, _IIter> && convertible_to<_Out1, _OOut1> - && convertible_to<_O2, _OOut2> - operator partition_copy_result<_IIter, _OOut1, _OOut2>() && + && convertible_to<_Out2, _OOut2> + constexpr + operator in_out_out_result<_IIter, _OOut1, _OOut2>() && { return {std::move(in), std::move(out1), std::move(out2)}; } }; + template + using partition_copy_result = in_out_out_result<_Iter, _Out1, _Out2>; + struct __partition_copy_fn { template _Sent, @@ -2692,7 +2712,7 @@ namespace ranges inline constexpr __partition_point_fn partition_point{}; template - using merge_result = binary_transform_result<_Iter1, _Iter2, _Out>; + using merge_result = in_in_out_result<_Iter1, _Iter2, _Out>; struct __merge_fn { @@ -2834,7 +2854,7 @@ namespace ranges inline constexpr __includes_fn includes{}; template - using set_union_result = binary_transform_result<_Iter1, _Iter2, _Out>; + using set_union_result = in_in_out_result<_Iter1, _Iter2, _Out>; struct __set_union_fn { @@ -2902,8 +2922,7 @@ namespace ranges inline constexpr __set_union_fn set_union{}; template - using set_intersection_result - = binary_transform_result<_Iter1, _Iter2, _Out>; + using set_intersection_result = in_in_out_result<_Iter1, _Iter2, _Out>; struct __set_intersection_fn { @@ -2961,7 +2980,7 @@ namespace ranges inline constexpr __set_intersection_fn set_intersection{}; template - using set_difference_result = copy_result<_Iter, _Out>; + using set_difference_result = in_out_result<_Iter, _Out>; struct __set_difference_fn { @@ -3019,7 +3038,7 @@ namespace ranges template using set_symmetric_difference_result - = binary_transform_result<_Iter1, _Iter2, _Out>; + = in_in_out_result<_Iter1, _Iter2, _Out>; struct __set_symmetric_difference_fn { @@ -3218,22 +3237,27 @@ namespace ranges inline constexpr __clamp_fn clamp{}; template - struct minmax_result + struct min_max_result { [[no_unique_address]] _Tp min; [[no_unique_address]] _Tp max; template requires convertible_to - operator minmax_result<_Tp2>() const & + constexpr + operator min_max_result<_Tp2>() const & { return {min, max}; } template requires convertible_to<_Tp, _Tp2> - operator minmax_result<_Tp2>() && + constexpr + operator min_max_result<_Tp2>() && { return {std::move(min), std::move(max)}; } }; + template + using minmax_result = min_max_result<_Tp>; + struct __minmax_fn { template - using minmax_element_result = minmax_result<_Iter>; + using minmax_element_result = min_max_result<_Iter>; struct __minmax_element_fn { @@ -3516,12 +3540,27 @@ namespace ranges inline constexpr __lexicographical_compare_fn lexicographical_compare; template - struct next_permutation_result + struct in_found_result { + [[no_unique_address]] _Iter in; bool found; - _Iter in; + + template + requires convertible_to + constexpr + operator in_found_result<_Iter2>() const & + { return {in, found}; } + + template + requires convertible_to<_Iter, _Iter2> + constexpr + operator in_found_result<_Iter2>() && + { return {std::move(in), found}; } }; + template + using next_permutation_result = in_found_result<_Iter>; + struct __next_permutation_fn { template _Sent, @@ -3532,12 +3571,12 @@ namespace ranges _Comp __comp = {}, _Proj __proj = {}) const { if (__first == __last) - return {false, std::move(__first)}; + return {std::move(__first), false}; auto __i = __first; ++__i; if (__i == __last) - return {false, std::move(__i)}; + return {std::move(__i), false}; auto __lasti = ranges::next(__first, __last); __i = __lasti; @@ -3558,12 +3597,12 @@ namespace ranges ; ranges::iter_swap(__i, __j); ranges::reverse(__ii, __last); - return {true, std::move(__lasti)}; + return {std::move(__lasti), true}; } if (__i == __first) { ranges::reverse(__first, __last); - return {false, std::move(__lasti)}; + return {std::move(__lasti), false}; } } } @@ -3582,7 +3621,7 @@ namespace ranges inline constexpr __next_permutation_fn next_permutation{}; template - using prev_permutation_result = next_permutation_result<_Iter>; + using prev_permutation_result = in_found_result<_Iter>; struct __prev_permutation_fn { @@ -3594,12 +3633,12 @@ namespace ranges _Comp __comp = {}, _Proj __proj = {}) const { if (__first == __last) - return {false, std::move(__first)}; + return {std::move(__first), false}; auto __i = __first; ++__i; if (__i == __last) - return {false, std::move(__i)}; + return {std::move(__i), false}; auto __lasti = ranges::next(__first, __last); __i = __lasti; @@ -3620,12 +3659,12 @@ namespace ranges ; ranges::iter_swap(__i, __j); ranges::reverse(__ii, __last); - return {true, std::move(__lasti)}; + return {std::move(__lasti), true}; } if (__i == __first) { ranges::reverse(__first, __last); - return {false, std::move(__lasti)}; + return {std::move(__lasti), false}; } } } diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h index eedd29f570a..7424766f053 100644 --- a/libstdc++-v3/include/bits/ranges_algobase.h +++ b/libstdc++-v3/include/bits/ranges_algobase.h @@ -157,7 +157,7 @@ namespace ranges inline constexpr __equal_fn equal{}; template - struct copy_result + struct in_out_result { [[no_unique_address]] _Iter in; [[no_unique_address]] _Out out; @@ -165,24 +165,29 @@ namespace ranges template requires convertible_to && convertible_to - operator copy_result<_Iter2, _Out2>() const & + constexpr + operator in_out_result<_Iter2, _Out2>() const & { return {in, out}; } template requires convertible_to<_Iter, _Iter2> && convertible_to<_Out, _Out2> - operator copy_result<_Iter2, _Out2>() && + constexpr + operator in_out_result<_Iter2, _Out2>() && { return {std::move(in), std::move(out)}; } }; template - using move_result = copy_result<_Iter, _Out>; + using copy_result = in_out_result<_Iter, _Out>; + + template + using move_result = in_out_result<_Iter, _Out>; template - using move_backward_result = copy_result<_Iter1, _Iter2>; + using move_backward_result = in_out_result<_Iter1, _Iter2>; template - using copy_backward_result = copy_result<_Iter1, _Iter2>; + using copy_backward_result = in_out_result<_Iter1, _Iter2>; template _Sent, @@ -483,7 +488,7 @@ namespace ranges inline constexpr __move_backward_fn move_backward{}; template - using copy_n_result = copy_result<_Iter, _Out>; + using copy_n_result = in_out_result<_Iter, _Out>; struct __copy_n_fn { diff --git a/libstdc++-v3/include/bits/ranges_uninitialized.h b/libstdc++-v3/include/bits/ranges_uninitialized.h index bbf683de066..881bf39d5f8 100644 --- a/libstdc++-v3/include/bits/ranges_uninitialized.h +++ b/libstdc++-v3/include/bits/ranges_uninitialized.h @@ -253,7 +253,7 @@ namespace ranges uninitialized_value_construct_n; template - using uninitialized_copy_result = copy_result<_Iter, _Out>; + using uninitialized_copy_result = in_out_result<_Iter, _Out>; struct __uninitialized_copy_fn { @@ -302,7 +302,7 @@ namespace ranges inline constexpr __uninitialized_copy_fn uninitialized_copy{}; template - using uninitialized_copy_n_result = uninitialized_copy_result<_Iter, _Out>; + using uninitialized_copy_n_result = in_out_result<_Iter, _Out>; struct __uninitialized_copy_n_fn { @@ -337,7 +337,7 @@ namespace ranges inline constexpr __uninitialized_copy_n_fn uninitialized_copy_n{}; template - using uninitialized_move_result = uninitialized_copy_result<_Iter, _Out>; + using uninitialized_move_result = in_out_result<_Iter, _Out>; struct __uninitialized_move_fn { @@ -389,7 +389,7 @@ namespace ranges inline constexpr __uninitialized_move_fn uninitialized_move{}; template - using uninitialized_move_n_result = uninitialized_copy_result<_Iter, _Out>; + using uninitialized_move_n_result = in_out_result<_Iter, _Out>; struct __uninitialized_move_n_fn { diff --git a/libstdc++-v3/testsuite/25_algorithms/next_permutation/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/next_permutation/constrained.cc index e69b551a56b..b397a4e8ed7 100644 --- a/libstdc++-v3/testsuite/25_algorithms/next_permutation/constrained.cc +++ b/libstdc++-v3/testsuite/25_algorithms/next_permutation/constrained.cc @@ -41,7 +41,7 @@ test01() for (int j = 0; ; j++) { auto found1 = std::next_permutation(cx.begin(), cx.end()); - auto [found2,last] = ranges::next_permutation(cy.begin(), cy.end()); + auto [last,found2] = ranges::next_permutation(cy.begin(), cy.end()); VERIFY( found1 == found2 ); VERIFY( ranges::equal(cx, cy) ); if (!found2) @@ -55,7 +55,7 @@ test02() { int x[] = {5, 4, 3, 2, 1}; test_range rx(x); - auto [found,last] = ranges::next_permutation(rx, ranges::greater{}); + auto [last,found] = ranges::next_permutation(rx, ranges::greater{}); VERIFY( found && last == rx.end() ); VERIFY( last == rx.end() ); VERIFY( ranges::equal(rx, (int[]){5,4,3,1,2}) ); diff --git a/libstdc++-v3/testsuite/25_algorithms/prev_permutation/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/prev_permutation/constrained.cc index 25bbad9be0c..22f1329b4c7 100644 --- a/libstdc++-v3/testsuite/25_algorithms/prev_permutation/constrained.cc +++ b/libstdc++-v3/testsuite/25_algorithms/prev_permutation/constrained.cc @@ -41,7 +41,7 @@ test01() for (int j = 0; ; j++) { auto found1 = std::prev_permutation(cx.begin(), cx.end()); - auto [found2,last] = ranges::prev_permutation(cy.begin(), cy.end()); + auto [last,found2] = ranges::prev_permutation(cy.begin(), cy.end()); VERIFY( found1 == found2 ); VERIFY( ranges::equal(cx, cy) ); if (!found2) @@ -55,7 +55,7 @@ test02() { int x[] = {1, 2, 3, 4, 5}; test_range rx(x); - auto [found,last] = ranges::prev_permutation(rx, ranges::greater{}); + auto [last,found] = ranges::prev_permutation(rx, ranges::greater{}); VERIFY( found && last == rx.end() ); VERIFY( last == rx.end() ); VERIFY( ranges::equal(rx, (int[]){1,2,3,5,4}) );