From patchwork Fri Nov 17 15:49:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 166275 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:9910:0:b0:403:3b70:6f57 with SMTP id i16csp678278vqn; Fri, 17 Nov 2023 09:08:58 -0800 (PST) X-Google-Smtp-Source: AGHT+IFi38Ph/+IY5mNEibKWRPmHHWeK8aYDD5GCo9oY6NcSS9L0PvdBt3z28aFym7vh4YoJdDf2 X-Received: by 2002:a05:6214:1302:b0:65d:475a:a2f6 with SMTP id pn2-20020a056214130200b0065d475aa2f6mr19088749qvb.40.1700240938624; Fri, 17 Nov 2023 09:08:58 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1700240938; cv=pass; d=google.com; s=arc-20160816; b=wZYLtXZSTmj+0umH8uXl9yCPv5LnFBQDGbqBHss1AeMNi/M4Mxd13fNk7UXPZzx8je D5s533E4fkNxh93mLJo1fny7Wld8gm2BWLCYgnkSycRTJR/PjC+2wQVXFFpkv6unsYVb T78CPZ8cyBA2MCV6uArwL3JSPEQvIhZ6OoYMfsvSWPgOY7asppOsnpWrToaJwtdtXYLt PDEB3Rcj4wedG7DqqvUk7wVx1Rz8qFMg2AthiMI3O7qVPYtknkGoPzNxBfD8S5GRZ178 YSUx9znq+8csd+lXZzjTumw6SfgmsWOwLdTofPsxP6LS7J6uX0aOgR2V0jJK9Qail7XO 5IUw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:to:from:dkim-signature :arc-filter:dmarc-filter:delivered-to; bh=AEeRFidqmtR8KRiF1NoW/2ERvU6jTB2Wu+r2LOU2m4Q=; fh=sJ+2/4g29YdyXkoRrFZSpsL2zxijepB7X/1rB0LDDh8=; b=iMuoD8tuhtSRMTQAYAwkkX8adK46Eyk80wK/vgC7wP7vixRJx4IfinF6eE+3jb68e4 tblqiAX51qusq8m/M+1EowOSQ2fnW/O7hphfeHAolGWQ3h6XXuEavkug2WfIocIcO6Ev 7jCIWISiBy0xbG6U/fDAHHCHXfKuhXqPiw24NNNHedSe64+zacnguPAis/cxQS3iKCpy a2IGz01AOxL/FYRvdl9D6OCMjoNunwWX39KKSR0caEB2oGgHJMns2Qzrvz+c0ip4vPgN 5kjFBHcdCw3yG2zdyokJrRMkwV8+Fx7MyJsSApQMCqmecv3veY+okNDbkY9UpubkllU9 5FCQ== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=jAy8AZf+; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id t12-20020a056214118c00b0066d20f29e50si2043463qvv.46.2023.11.17.09.08.58 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Nov 2023 09:08:58 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=jAy8AZf+; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A795E3857C4A for ; Fri, 17 Nov 2023 15:53:30 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id AC2CE3858C98 for ; Fri, 17 Nov 2023 15:53:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org AC2CE3858C98 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 AC2CE3858C98 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700236386; cv=none; b=FIVIOvQ8uBKYXGcEsLGIXbcDAhq9Al1ZxQ7djS7u+ooRX7H+6OR8T/yKOBTlcU2MmJHasYmf/WWErFYhhfofMDdLp9RL9a77NRwHbSOFLQKyAUZ7U1r084qxtGIMbnkUDAMqRvAI3UfPaL+TFQHLXKYvg59BxewDtExEtcjHPhc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700236386; c=relaxed/simple; bh=gQXLl6x0nzKD56CXq55jaSrPCesnM8Q3zAnwJ90Oh/E=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=AIkjHGVpRTXRtXgyRzi2dr16StuFivW4Ni0siXCRshWoJ9ZTV3nWDo//oiwnVNBtxYozTnnGTdyZVWXiLPDb7sRFaVXfKcQ2FYUbXitQsAbq8BpfxUFX2Oz1fNpQhfWr9V8mYSWKwk8kXgkpyo6l/AS+sIEoKwmS/HaO2VcWwVc= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1700236384; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=AEeRFidqmtR8KRiF1NoW/2ERvU6jTB2Wu+r2LOU2m4Q=; b=jAy8AZf+oddqYveVRo8/jEoPi57j1A3W5cVCeloUn8ukttK+uAZ7JYcwjyE7CrUk3MvTuP ewkWZEGuXyooctf9eQAcsNJfRgtzX7p29nqaEjx9G51Z0byD69isOXi+1p9OaXcZU0fWbv cRnCceiff4ptvq0XLx985CD38R9pMfY= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-53-tG1Yh8jJOe-_DVuaC3Mz1A-1; Fri, 17 Nov 2023 10:53:01 -0500 X-MC-Unique: tG1Yh8jJOe-_DVuaC3Mz1A-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 5F8EE185A785; Fri, 17 Nov 2023 15:53:01 +0000 (UTC) Received: from localhost (unknown [10.42.28.9]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0FB6F492BFE; Fri, 17 Nov 2023 15:53:00 +0000 (UTC) From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [PATCH] libstdc++: Define std::ranges::to for C++23 (P1206R7) [PR111055] Date: Fri, 17 Nov 2023 15:49:47 +0000 Message-ID: <20231117155300.1513586-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.10 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-13.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_H4, RCVD_IN_MSPIKE_WL, 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.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1782831842413606998 X-GMAIL-MSGID: 1782831842413606998 This needs tests, and doesn't include the changes to the standard containers to add insert_range etc. (but they work with ranges::to anyway, using the existing member functions). I plan to write the tests and push this tomorrow. I've trimmed the boring bits of the version.h changes, that are caused just by reordering some existing entries to be in alphabetical order. -- >8 -- libstdc++-v3/ChangeLog: PR libstdc++/111055 * include/bits/ranges_base.h (from_range_t): Define new tag type. (from_range): Define new tag object. * include/bits/version.def (ranges_to_container): Define. * include/bits/version.h: Regenerate. * include/std/ranges (ranges::to): Define. --- libstdc++-v3/include/bits/ranges_base.h | 6 + libstdc++-v3/include/bits/version.def | 34 ++- libstdc++-v3/include/bits/version.h | 111 +++++----- libstdc++-v3/include/std/ranges | 279 +++++++++++++++++++++++- 4 files changed, 371 insertions(+), 59 deletions(-) diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index 7fa43d1965a..555065b4ed7 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef __cpp_lib_concepts namespace std _GLIBCXX_VISIBILITY(default) @@ -1057,6 +1058,11 @@ namespace ranges iterator_t<_Range>, dangling>; +#if __glibcxx_ranges_to_container // C++ >= 23 + struct from_range_t { explicit from_range_t() = default; }; + inline constexpr from_range_t from_range{}; +#endif + } // namespace ranges _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 447fdeb9519..15bd502f52c 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -1370,19 +1370,21 @@ ftms = { }; }; -ftms = { - name = to_underlying; - values = { - v = 202102; - cxxmin = 23; - }; -}; +//ftms = { +// name = container_ranges; +// values = { +// v = 202202; +// cxxmin = 23; +// hosted = yes; +// }; +//}; ftms = { - name = unreachable; + name = ranges_to_container; values = { v = 202202; cxxmin = 23; + hosted = yes; }; }; @@ -1614,6 +1616,22 @@ ftms = { }; }; +ftms = { + name = to_underlying; + values = { + v = 202102; + cxxmin = 23; + }; +}; + +ftms = { + name = unreachable; + values = { + v = 202202; + cxxmin = 23; + }; +}; + ftms = { name = fstream_native_handle; values = { diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 97c6d8508f4..9563b6cd2f7 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -1658,29 +1658,18 @@ #endif /* !defined(__cpp_lib_reference_from_temporary) && defined(__glibcxx_want_reference_from_temporary) */ #undef __glibcxx_want_reference_from_temporary -// from version.def line 1374 -#if !defined(__cpp_lib_to_underlying) -# if (__cplusplus >= 202100L) -# define __glibcxx_to_underlying 202102L -# if defined(__glibcxx_want_all) || defined(__glibcxx_want_to_underlying) -# define __cpp_lib_to_underlying 202102L +// from version.def line 1383 +#if !defined(__cpp_lib_ranges_to_container) +# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED +# define __glibcxx_ranges_to_container 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_to_container) +# define __cpp_lib_ranges_to_container 202202L # endif # endif -#endif /* !defined(__cpp_lib_to_underlying) && defined(__glibcxx_want_to_underlying) */ -#undef __glibcxx_want_to_underlying +#endif /* !defined(__cpp_lib_ranges_to_container) && defined(__glibcxx_want_ranges_to_container) */ +#undef __glibcxx_want_ranges_to_container -// from version.def line 1382 -#if !defined(__cpp_lib_unreachable) -# if (__cplusplus >= 202100L) -# define __glibcxx_unreachable 202202L -# if defined(__glibcxx_want_all) || defined(__glibcxx_want_unreachable) -# define __cpp_lib_unreachable 202202L -# endif -# endif -#endif /* !defined(__cpp_lib_unreachable) && defined(__glibcxx_want_unreachable) */ -#undef __glibcxx_want_unreachable - -// from version.def line 1390 +// from version.def line 1392 #if !defined(__cpp_lib_ranges_zip) # if (__cplusplus >= 202100L) # define __glibcxx_ranges_zip 202110L @@ -1977,7 +1966,29 @@ #endif /* !defined(__cpp_lib_string_resize_and_overwrite) && defined(__glibcxx_want_string_resize_and_overwrite) */ #undef __glibcxx_want_string_resize_and_overwrite -// from version.def line 1618 +// from version.def line 1620 +#if !defined(__cpp_lib_to_underlying) +# if (__cplusplus >= 202100L) +# define __glibcxx_to_underlying 202102L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_to_underlying) +# define __cpp_lib_to_underlying 202102L +# endif +# endif +#endif /* !defined(__cpp_lib_to_underlying) && defined(__glibcxx_want_to_underlying) */ +#undef __glibcxx_want_to_underlying + +// from version.def line 1628 +#if !defined(__cpp_lib_unreachable) +# if (__cplusplus >= 202100L) +# define __glibcxx_unreachable 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_unreachable) +# define __cpp_lib_unreachable 202202L +# endif +# endif +#endif /* !defined(__cpp_lib_unreachable) && defined(__glibcxx_want_unreachable) */ +#undef __glibcxx_want_unreachable + +// from version.def line 1636 #if !defined(__cpp_lib_fstream_native_handle) # if (__cplusplus > 202302L) && _GLIBCXX_HOSTED # define __glibcxx_fstream_native_handle 202306L diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 26d6c013ad0..fcc0a786091 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -64,6 +64,7 @@ #define __glibcxx_want_ranges_repeat #define __glibcxx_want_ranges_slide #define __glibcxx_want_ranges_stride +#define __glibcxx_want_ranges_to_container #define __glibcxx_want_ranges_zip #include @@ -9213,8 +9214,284 @@ namespace views::__adaptor namespace views = ranges::views; +#if __cpp_lib_ranges_to_container // C++ >= 23 +namespace ranges +{ +namespace __detail +{ + template + constexpr bool __reservable_container + = sized_range<_Container> + && requires(_Container& __c, range_size_t<_Container> __n) { + __c.reserve(__n); + { __c.capacity() } -> same_as; + { __c.max_size() } -> same_as; + }; + + template + constexpr bool __container_insertable + = requires(_Container& __c, _Ref&& __ref) { + requires (requires { __c.push_back(std::forward<_Ref>(__ref)); } + || requires { __c.insert(__c.end(), std::forward<_Ref>(__ref)); }); + }; + + template + constexpr auto + __container_inserter(_Container& __c) + { + if constexpr (requires { __c.push_back(std::declval<_Ref>()); }) + return back_inserter(__c); + else + return inserter(__c, __c.end()); + } + + template + struct _InputIter + { + using iterator_category = input_iterator_tag; + using value_type = range_value_t<_Rg>; + using difference_type = ptrdiff_t; + using pointer = add_pointer_t>; + using reference = range_reference_t<_Rg>; + reference operator*() const; + pointer operator->() const; + _InputIter& operator++(); + _InputIter operator++(int); + bool operator==(const _InputIter&) const; + }; + + template typename _Cont, typename _Rg, + typename... _Args> + concept __deduce_expr_1 = requires { + _Cont(std::declval<_Rg>(), std::declval<_Args>()...); + }; + + template typename _Cont, typename _Rg, + typename... _Args> + concept __deduce_expr_2 = requires { + _Cont(from_range, std::declval<_Rg>(), std::declval<_Args>()...); + }; + + template typename _Cont, typename _Rg, + typename... _Args> + concept __deduce_expr_3 = requires(_InputIter<_Rg> __i) { + _Cont(std::move(__i), std::move(__i), std::declval<_Args>()...); + }; + + template typename _Cont, input_range _Rg, + typename... _Args> + using _DeduceExpr1 + = decltype(_Cont(std::declval<_Rg>(), std::declval<_Args>()...)); + + template typename _Cont, input_range _Rg, + typename... _Args> + using _DeduceExpr2 + = decltype(_Cont(from_range, std::declval<_Rg>(), + std::declval<_Args>()...)); + + template typename _Cont, input_range _Rg, + typename... _Args> + using _DeduceExpr3 + = decltype(_Cont(std::declval<_InputIter<_Rg>>(), + std::declval<_InputIter<_Rg>>(), + std::declval<_Args>()...)); + +} // namespace __detail + + template + requires (!view<_Cont>) + constexpr _Cont + to(_Rg&& __r, _Args&&... __args) + { + static_assert(!is_const_v<_Cont> && !is_volatile_v<_Cont>); + static_assert(is_class_v<_Cont>); + if constexpr (!input_range<_Cont> + || convertible_to, range_value_t<_Cont>>) + { + if constexpr (constructible_from<_Cont, _Rg, _Args...>) + return _Cont(std::forward<_Rg>(__r), + std::forward<_Args>(__args)...); + else if constexpr (constructible_from<_Cont, from_range_t, _Rg, _Args...>) + return _Cont(from_range, std::forward<_Rg>(__r), + std::forward<_Args>(__args)...); + else if constexpr (common_range<_Rg> + && derived_from<__iter_category_t>, + input_iterator_tag> + && constructible_from<_Cont, iterator_t<_Rg>, sentinel_t<_Rg>, + _Args...>) + return _Cont(ranges::begin(__r), ranges::end(__r), + std::forward<_Args>(__args)...); + else + { + using __detail::__container_insertable; + using __detail::__reservable_container; + using _RefT = range_reference_t<_Rg>; + static_assert(constructible_from<_Cont, _Args...>); + static_assert(__container_insertable<_Cont, _RefT>); + _Cont __c(std::forward<_Args>(__args)...); + if constexpr (sized_range<_Rg> && __reservable_container<_Cont>) + __c.reserve(static_cast>(ranges::size(__r))); + auto __ins = __detail::__container_inserter<_RefT>(__c); + for (auto&& __e : __r) + *__ins++ = std::forward(__e); + return __c; + } + } + else + { + static_assert(input_range>); + return ranges::to<_Cont>(__r | views::transform( // XXX not in scope + [](_Elt&& __elem) { + using _ValT = range_value_t<_Cont>; + return ranges::to<_ValT>(std::forward<_Elt>(__elem)); + }), std::forward<_Args>(__args)...); + } + } + + template typename _Cont, input_range _Rg, + typename... _Args> + constexpr auto + to(_Rg&& __r, _Args&&... __args) + { + using __detail::_DeduceExpr1; + using __detail::_DeduceExpr2; + using __detail::_DeduceExpr3; + if constexpr (requires { typename _DeduceExpr1<_Cont, _Rg, _Args...>; }) + return ranges::to<_DeduceExpr1<_Cont, _Rg, _Args...>>( + std::forward<_Rg>(__r), std::forward<_Args>(__args)...); + else if constexpr (requires { typename _DeduceExpr2<_Cont, _Rg, _Args...>; }) + return ranges::to<_DeduceExpr2<_Cont, _Rg, _Args...>>( + std::forward<_Rg>(__r), std::forward<_Args>(__args)...); + else if constexpr (requires { typename _DeduceExpr3<_Cont, _Rg, _Args...>; }) + return ranges::to<_DeduceExpr3<_Cont, _Rg, _Args...>>( + std::forward<_Rg>(__r), std::forward<_Args>(__args)...); + else + static_assert(false); // Cannot deduce container specialization. + } + + template + class _ToClosure + : public views::__adaptor::_RangeAdaptorClosure<_ToClosure<_Cont, _Args...>> + { + tuple...> _M_bound_args; + + public: + _ToClosure(_Args&&... __args) + : _M_bound_args(std::forward<_Args>(__args)...) + { } + + // TODO: use explicit object functions ("deducing this"). + + template + constexpr auto + operator()(_Rg&& __r) & + { + return std::apply([&__r](_Tp&&... __args) { + return ranges::to<_Cont>(std::forward<_Rg>(__r), + std::forward<_Tp>(__args)...); + }, _M_bound_args); + } + + template + constexpr auto + operator()(_Rg&& __r) const & + { + return std::apply([&__r](_Tp&&... __args) { + return ranges::to<_Cont>(std::forward<_Rg>(__r), + std::forward<_Tp>(__args)...); + }, _M_bound_args); + } + + template + constexpr auto + operator()(_Rg&& __r) && + { + return std::apply([&__r](_Tp&&... __args) { + return ranges::to<_Cont>(std::forward<_Rg>(__r), + std::forward<_Tp>(__args)...); + }, std::move(_M_bound_args)); + } + + template + constexpr auto + operator()(_Rg&& __r) const && + { + return std::apply([&__r](_Tp&&... __args) { + return ranges::to<_Cont>(std::forward<_Rg>(__r), + std::forward<_Tp>(__args)...); + }, std::move(_M_bound_args)); + } + }; + + template + requires (!view<_Cont>) + constexpr _ToClosure<_Cont, _Args...> + to(_Args&&... __args) + { return {std::forward<_Args>(__args)...}; } + + template typename _Cont, typename... _Args> + class _ToClosure2 + : public views::__adaptor::_RangeAdaptorClosure<_ToClosure2<_Cont, _Args...>> + { + tuple...> _M_bound_args; + + public: + _ToClosure2(_Args&&... __args) + : _M_bound_args(std::forward<_Args>(__args)...) + { } + + // TODO: use explicit object functions ("deducing this"). + + template + constexpr auto + operator()(_Rg&& __r) & + { + return std::apply([&__r](_Tp&&... __args) { + return ranges::to<_Cont>(std::forward<_Rg>(__r), + std::forward<_Tp>(__args)...); + }, _M_bound_args); + } + + template + constexpr auto + operator()(_Rg&& __r) const & + { + return std::apply([&__r](_Tp&&... __args) { + return ranges::to<_Cont>(std::forward<_Rg>(__r), + std::forward<_Tp>(__args)...); + }, _M_bound_args); + } + + template + constexpr auto + operator()(_Rg&& __r) && + { + return std::apply([&__r](_Tp&&... __args) { + return ranges::to<_Cont>(std::forward<_Rg>(__r), + std::forward<_Tp>(__args)...); + }, std::move(_M_bound_args)); + } + + template + constexpr auto + operator()(_Rg&& __r) const && + { + return std::apply([&__r](_Tp&&... __args) { + return ranges::to<_Cont>(std::forward<_Rg>(__r), + std::forward<_Tp>(__args)...); + }, std::move(_M_bound_args)); + } + }; + + template typename _Cont, typename... _Args> + constexpr _ToClosure2<_Cont, _Args...> + to(_Args&&... __args) + { return {std::forward<_Args>(__args)...}; } +} // namespace ranges +#endif // __cpp_lib_ranges_to_container + _GLIBCXX_END_NAMESPACE_VERSION -} // namespace +} // namespace std #endif // library concepts #endif // C++2a #endif /* _GLIBCXX_RANGES */