From patchwork Fri Oct 1 19:42:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 45716 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 63745385741A for ; Fri, 1 Oct 2021 19:56:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 63745385741A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1633118194; bh=2su/f/Gf8ik6QPMTdQa+ZrUPVNMoH7nQQTtdO4BAnNY=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=y21W6dudRRHpo169ax8HSM9IN0qOQF/DkKWq+GjIBuXauYQm5aRNvhvgeerk5Gppq F/0j+8fBhkoExCflW2GVuWOPll5WOB2+4ihk+MHeS1djpfhzD5AlIlGCwV1g/r3V9B v0VoKebHryhlN1eMuTXp7SoYEGF3W5LbbQ3AfkOw= 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 B45413857810 for ; Fri, 1 Oct 2021 19:42:30 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org B45413857810 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-296-_vcQJS6jOoij66FHz_d1NQ-1; Fri, 01 Oct 2021 15:42:29 -0400 X-MC-Unique: _vcQJS6jOoij66FHz_d1NQ-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 46AE1196635D; Fri, 1 Oct 2021 19:42:28 +0000 (UTC) Received: from localhost (unknown [10.33.36.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id E92261972D; Fri, 1 Oct 2021 19:42:27 +0000 (UTC) Date: Fri, 1 Oct 2021 20:42:27 +0100 To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Allow visiting inherited variants [PR 90943] Message-ID: MIME-Version: 1.0 X-Clacks-Overhead: GNU Terry Pratchett X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-13.8 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_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham 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: Jonathan Wakely via Gcc-patches From: Jonathan Wakely Reply-To: Jonathan Wakely Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Implement the changes from P2162R2 (as a DR for C++17). Signed-off-by: Jonathan Wakely libstdc++-v3/ChangeLog: PR libstdc++/90943 * include/std/variant (__cpp_lib_variant): Update value. (__detail::__variant::__as): New helpers implementing the as-variant exposition-only function templates. (visit, visit): Use __as to upcast the variant parameters. * include/std/version (__cpp_lib_variant): Update value. * testsuite/20_util/variant/visit_inherited.cc: New test. Tested powerpc64le-linux. Committed to trunk. commit c46ecb0112e91c80ee111439e79a58a953e4479d Author: Jonathan Wakely Date: Mon Apr 19 14:49:12 2021 libstdc++: Allow visiting inherited variants [PR 90943] Implement the changes from P2162R2 (as a DR for C++17). Signed-off-by: Jonathan Wakely libstdc++-v3/ChangeLog: PR libstdc++/90943 * include/std/variant (__cpp_lib_variant): Update value. (__detail::__variant::__as): New helpers implementing the as-variant exposition-only function templates. (visit, visit): Use __as to upcast the variant parameters. * include/std/version (__cpp_lib_variant): Update value. * testsuite/20_util/variant/visit_inherited.cc: New test. diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index 6383cf4e502..c651326ead9 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -71,7 +71,7 @@ namespace __variant } // namespace __variant } // namespace __detail -#define __cpp_lib_variant 201606L +#define __cpp_lib_variant 202102L template class tuple; template class variant; @@ -202,6 +202,28 @@ namespace __variant std::forward<_Variants>(__variants)...); } + // The __as function templates implement the exposition-only "as-variant" + + template + constexpr std::variant<_Types...>& + __as(std::variant<_Types...>& __v) + { return __v; } + + template + constexpr const std::variant<_Types...>& + __as(const std::variant<_Types...>& __v) noexcept + { return __v; } + + template + constexpr std::variant<_Types...>&& + __as(std::variant<_Types...>&& __v) noexcept + { return std::move(__v); } + + template + constexpr const std::variant<_Types...>&& + __as(const std::variant<_Types...>&& __v) noexcept + { return std::move(__v); } + // _Uninitialized is guaranteed to be a trivially destructible type, // even if T is not. template> @@ -1063,8 +1085,12 @@ namespace __variant std::index_sequence<__indices...>> : _Base_dedup<__indices, __poison_hash>>... { }; - template - using __get_t = decltype(std::get<_Np>(std::declval<_Variant>())); + // Equivalent to decltype(get<_Np>(as-variant(declval<_Variant>()))) + template())), + typename _Tp = variant_alternative_t<_Np, remove_reference_t<_AsV>>> + using __get_t + = conditional_t, _Tp&, _Tp&&>; // Return type of std::visit. template @@ -1741,7 +1767,9 @@ namespace __variant constexpr __detail::__variant::__visit_result_t<_Visitor, _Variants...> visit(_Visitor&& __visitor, _Variants&&... __variants) { - if ((__variants.valueless_by_exception() || ...)) + namespace __variant = std::__detail::__variant; + + if ((__variant::__as(__variants).valueless_by_exception() || ...)) __throw_bad_variant_access("std::visit: variant is valueless"); using _Result_type @@ -1751,10 +1779,11 @@ namespace __variant if constexpr (sizeof...(_Variants) == 1) { + using _Vp = decltype(__variant::__as(std::declval<_Variants>()...)); + constexpr bool __visit_rettypes_match = __detail::__variant:: - __check_visitor_results<_Visitor, _Variants...>( - std::make_index_sequence< - std::variant_size...>::value>()); + __check_visitor_results<_Visitor, _Vp>( + make_index_sequence>>()); if constexpr (!__visit_rettypes_match) { static_assert(__visit_rettypes_match, @@ -1765,12 +1794,12 @@ namespace __variant else return std::__do_visit<_Tag>( std::forward<_Visitor>(__visitor), - std::forward<_Variants>(__variants)...); + static_cast<_Vp>(__variants)...); } else return std::__do_visit<_Tag>( std::forward<_Visitor>(__visitor), - std::forward<_Variants>(__variants)...); + __variant::__as(std::forward<_Variants>(__variants))...); } #if __cplusplus > 201703L @@ -1778,11 +1807,13 @@ namespace __variant constexpr _Res visit(_Visitor&& __visitor, _Variants&&... __variants) { - if ((__variants.valueless_by_exception() || ...)) + namespace __variant = std::__detail::__variant; + + if ((__variant::__as(__variants).valueless_by_exception() || ...)) __throw_bad_variant_access("std::visit: variant is valueless"); return std::__do_visit<_Res>(std::forward<_Visitor>(__visitor), - std::forward<_Variants>(__variants)...); + __variant::__as(std::forward<_Variants>(__variants))...); } #endif diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index f41004b5911..42f7dfa62ad 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -171,7 +171,7 @@ # define __cpp_lib_to_chars 201611L #endif #define __cpp_lib_unordered_map_try_emplace 201411 -#define __cpp_lib_variant 201606L +#define __cpp_lib_variant 202102L #endif #if __cplusplus >= 202002L diff --git a/libstdc++-v3/testsuite/20_util/variant/visit_inherited.cc b/libstdc++-v3/testsuite/20_util/variant/visit_inherited.cc new file mode 100644 index 00000000000..ade83096475 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/variant/visit_inherited.cc @@ -0,0 +1,36 @@ +// { dg-do compile { target c++17 } } + +#include + +// P2062R2 Inheriting from std::variant (resolving LWG 3052) + +#if __cpp_lib_variant < 202102L +#error __cpp_lib_variant has the wrong value in +#endif + +struct V : std::variant { + using std::variant::variant; +}; + +constexpr int +test01() +{ + V v = 42; + return std::visit([](int&){ return 17; }, v); +} +static_assert( test01() == 17 ); + +constexpr int +test02() +{ + const V c = 77; + std::variant x = 88L; + return std::visit([](auto&& a, auto&& b) { + if constexpr (std::is_same_v) + if constexpr (std::is_same_v) + return 99; + return 0; + }, + std::move(c), std::move(x)); +} +static_assert( test02() == 99 );