libstdc++: Consolidate bullet 1 __common_reference_impl partial specs

... and in passing use requires-clauses instead of void_t based SFINAE.
This is a non-functional change that'll simplify implementing the
P2655R3 change to common_reference.

	PR c++/120446

libstdc++-v3/ChangeLog:

	* include/std/type_traits (__common_reference_impl): Rewrite
	partial specializations to use requires-clause instead of
	an additional void_t template parameter.  Consolidate the
	partial specializations corresponding to bullet 1.

Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
This commit is contained in:
Patrick Palka
2025-12-05 13:43:26 -05:00
parent 5d5eeb3709
commit cbdbbdd1fc

View File

@@ -4225,7 +4225,7 @@ template<typename _Ret, typename _Fn, typename... _Args>
{ using type = _Tp0; };
/// @cond undocumented
template<typename _Tp1, typename _Tp2, int _Bullet = 1, typename = void>
template<typename _Tp1, typename _Tp2, int _Bullet = 1>
struct __common_reference_impl
: __common_reference_impl<_Tp1, _Tp2, _Bullet + 1>
{ };
@@ -4238,46 +4238,32 @@ template<typename _Ret, typename _Fn, typename... _Args>
// If T1 and T2 are reference types and COMMON-REF(T1, T2) is well-formed, ...
template<typename _Tp1, typename _Tp2>
struct __common_reference_impl<_Tp1&, _Tp2&, 1,
void_t<__common_ref<_Tp1&, _Tp2&>>>
{ using type = __common_ref<_Tp1&, _Tp2&>; };
template<typename _Tp1, typename _Tp2>
struct __common_reference_impl<_Tp1&&, _Tp2&&, 1,
void_t<__common_ref<_Tp1&&, _Tp2&&>>>
{ using type = __common_ref<_Tp1&&, _Tp2&&>; };
template<typename _Tp1, typename _Tp2>
struct __common_reference_impl<_Tp1&, _Tp2&&, 1,
void_t<__common_ref<_Tp1&, _Tp2&&>>>
{ using type = __common_ref<_Tp1&, _Tp2&&>; };
template<typename _Tp1, typename _Tp2>
struct __common_reference_impl<_Tp1&&, _Tp2&, 1,
void_t<__common_ref<_Tp1&&, _Tp2&>>>
{ using type = __common_ref<_Tp1&&, _Tp2&>; };
requires is_reference_v<_Tp1> && is_reference_v<_Tp2>
&& requires { typename __common_ref<_Tp1, _Tp2>; }
struct __common_reference_impl<_Tp1, _Tp2, 1>
{ using type = __common_ref<_Tp1, _Tp2>; };
// Otherwise, if basic_common_reference<...>::type is well-formed, ...
template<typename _Tp1, typename _Tp2>
struct __common_reference_impl<_Tp1, _Tp2, 2,
void_t<__basic_common_ref<_Tp1, _Tp2>>>
requires requires { typename __basic_common_ref<_Tp1, _Tp2>; }
struct __common_reference_impl<_Tp1, _Tp2, 2>
{ using type = __basic_common_ref<_Tp1, _Tp2>; };
// Otherwise, if COND-RES(T1, T2) is well-formed, ...
template<typename _Tp1, typename _Tp2>
struct __common_reference_impl<_Tp1, _Tp2, 3,
void_t<__cond_res<_Tp1, _Tp2>>>
requires requires { typename __cond_res<_Tp1, _Tp2>; }
struct __common_reference_impl<_Tp1, _Tp2, 3>
{ using type = __cond_res<_Tp1, _Tp2>; };
// Otherwise, if common_type_t<T1, T2> is well-formed, ...
template<typename _Tp1, typename _Tp2>
struct __common_reference_impl<_Tp1, _Tp2, 4,
void_t<common_type_t<_Tp1, _Tp2>>>
requires requires { typename common_type_t<_Tp1, _Tp2>; }
struct __common_reference_impl<_Tp1, _Tp2, 4>
{ using type = common_type_t<_Tp1, _Tp2>; };
// Otherwise, there shall be no member type.
template<typename _Tp1, typename _Tp2>
struct __common_reference_impl<_Tp1, _Tp2, 5, void>
struct __common_reference_impl<_Tp1, _Tp2, 5>
{ };
// Otherwise, if sizeof...(T) is greater than two, ...
@@ -4296,7 +4282,7 @@ template<typename _Ret, typename _Fn, typename... _Args>
{ };
/// @endcond
#endif // C++2a
#endif // C++20
#if __cplusplus >= 201103L
// Stores a tuple of indices. Used by tuple and pair, and by bind() to