From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2181) id 001A0385840C; Mon, 26 Sep 2022 22:48:30 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 001A0385840C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1664232511; bh=OauLrA0LYsPCHVhwUaFmvqoNmtUg9YW65gUocd8dG6I=; h=From:To:Subject:Date:From; b=rQzSlJZ2u1S2E9+Y7IyBa7tgBR29h/7guPkTQlv/X8V8jeInvozk8S2rvqW4c+/xX BfDLsvMczFwMaMHIfL0cxyhCtvp1goh4HzxgbuIdkD5vjILS2Qmg03T411Ju3xUXUH +9CnbKe9P4xIXEqaplaD4Qokh9oy3dnK9VPaB7uQ= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jonathan Wakely To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r13-2884] libstdc++: Update std::pointer_traits to match new LWG 3545 wording X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/heads/master X-Git-Oldrev: af85ad891703db220b25e7847f10d0bbec4becf4 X-Git-Newrev: 03cb9ed8dd603dbb77762ca948fc6381ba190731 Message-Id: <20220926224831.001A0385840C@sourceware.org> Date: Mon, 26 Sep 2022 22:48:30 +0000 (GMT) List-Id: https://gcc.gnu.org/g:03cb9ed8dd603dbb77762ca948fc6381ba190731 commit r13-2884-g03cb9ed8dd603dbb77762ca948fc6381ba190731 Author: Jonathan Wakely Date: Mon Sep 26 18:59:45 2022 +0100 libstdc++: Update std::pointer_traits to match new LWG 3545 wording It was pointed out in recent LWG 3545 discussion that having a constrained partial specialization of std::pointer_traits can cause ambiguities with program-defined specializations. For example, the addition to the testcase has: template requires std::derived_from; This would be ambiguous with the library's own constrained partial specialization: template requires requires { typename Ptr::element_type; } struct std::pointer_traits; Neither specialization is more specialized than the other for a type that is derived from base_type and also has an element_type member. The solution is to remove the library's partial specialization, and do the check for Ptr::element_type in the __ptr_traits_elem helper (which is what we already do for !__cpp_concepts anyway). libstdc++-v3/ChangeLog: * include/bits/ptr_traits.h (__ptr_traits_elem) [__cpp_concepts]: Also define the __ptr_traits_elem class template for the concepts case. (pointer_traits): Remove constrained partial specialization. * testsuite/20_util/pointer_traits/lwg3545.cc: Check for ambiguitiy with program-defined partial specialization. Diff: --- libstdc++-v3/include/bits/ptr_traits.h | 20 ++++++-------------- .../testsuite/20_util/pointer_traits/lwg3545.cc | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h index ae8810706ab..71370ff4fc9 100644 --- a/libstdc++-v3/include/bits/ptr_traits.h +++ b/libstdc++-v3/include/bits/ptr_traits.h @@ -73,25 +73,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __replace_first_arg<_SomeTemplate<_Tp, _Types...>, _Up> { using type = _SomeTemplate<_Up, _Types...>; }; -#if __cpp_concepts - // When concepts are supported detection of _Ptr::element_type is done - // by a requires-clause, so __ptr_traits_elem_t only needs to do this: - template - using __ptr_traits_elem_t = typename __get_first_arg<_Ptr>::type; -#else // Detect the element type of a pointer-like type. template struct __ptr_traits_elem : __get_first_arg<_Ptr> { }; // Use _Ptr::element_type if is a valid type. +#if __cpp_concepts + template requires requires { typename _Ptr::element_type; } + struct __ptr_traits_elem<_Ptr, void> + { using type = typename _Ptr::element_type; }; +#else template struct __ptr_traits_elem<_Ptr, __void_t> { using type = typename _Ptr::element_type; }; +#endif template using __ptr_traits_elem_t = typename __ptr_traits_elem<_Ptr>::type; -#endif /// @endcond @@ -182,13 +181,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct pointer_traits : __ptr_traits_impl<_Ptr, __ptr_traits_elem_t<_Ptr>> { }; -#if __cpp_concepts - template requires requires { typename _Ptr::element_type; } - struct pointer_traits<_Ptr> - : __ptr_traits_impl<_Ptr, typename _Ptr::element_type> - { }; -#endif - /** * @brief Partial specialization for built-in pointers. * @headerfile memory diff --git a/libstdc++-v3/testsuite/20_util/pointer_traits/lwg3545.cc b/libstdc++-v3/testsuite/20_util/pointer_traits/lwg3545.cc index 08c3ed01b75..93c64a353bd 100644 --- a/libstdc++-v3/testsuite/20_util/pointer_traits/lwg3545.cc +++ b/libstdc++-v3/testsuite/20_util/pointer_traits/lwg3545.cc @@ -99,3 +99,20 @@ static_assert( is_same, clever_ptr>::value, "" ); static_assert( is_same, std::ptrdiff_t>::value, "" ); static_assert( is_same, clever_ptr>::value, "" ); static_assert( is_same, clever_ptr>::value, "" ); + +#ifdef __cpp_concepts +struct ptr_base { }; + +// Program-defined specialization must not be ambiguous with primary template. +template requires std::derived_from +struct std::pointer_traits

+{ + using element_type = int; + using difference_type = long; + using pointer = P; +}; + +struct Ptr : ptr_base { using element_type = int; }; + +using E = std::pointer_traits::element_type; +#endif