@@ -2411,6 +2411,216 @@ struct _LIBCPP_TEMPLATE_VIS
24112411template <class ..._Tp> using common_type_t = typename common_type<_Tp...>::type;
24122412#endif
24132413
2414+ #if _LIBCPP_STD_VER > 11
2415+ // Let COPYCV(FROM, TO) be an alias for type TO with the addition of FROM’s
2416+ // top-level cv-qualifiers.
2417+ template <class _From , class _To >
2418+ struct __copy_cv
2419+ {
2420+ using type = _To;
2421+ };
2422+
2423+ template <class _From , class _To >
2424+ struct __copy_cv <const _From, _To>
2425+ {
2426+ using type = add_const_t <_To>;
2427+ };
2428+
2429+ template <class _From , class _To >
2430+ struct __copy_cv <volatile _From, _To>
2431+ {
2432+ using type = add_volatile_t <_To>;
2433+ };
2434+
2435+ template <class _From , class _To >
2436+ struct __copy_cv <const volatile _From, _To>
2437+ {
2438+ using type = add_cv_t <_To>;
2439+ };
2440+
2441+ template <class _From , class _To >
2442+ using __copy_cv_t = typename __copy_cv<_From, _To>::type;
2443+
2444+ template <class _From , class _To >
2445+ struct __copy_cvref
2446+ {
2447+ using type = __copy_cv_t <_From, _To>;
2448+ };
2449+
2450+ template <class _From , class _To >
2451+ struct __copy_cvref <_From&, _To>
2452+ {
2453+ using type = add_lvalue_reference_t <__copy_cv_t <_From, _To>>;
2454+ };
2455+
2456+ template <class _From , class _To >
2457+ struct __copy_cvref <_From&&, _To>
2458+ {
2459+ using type = add_rvalue_reference_t <__copy_cv_t <_From, _To>>;
2460+ };
2461+
2462+ template <class _From , class _To >
2463+ using __copy_cvref_t = typename __copy_cvref<_From, _To>::type;
2464+
2465+ #endif // _LIBCPP_STD_VER > 11
2466+
2467+ // common_reference
2468+ #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
2469+ // Let COND_RES(X, Y) be:
2470+ template <class _Xp , class _Yp >
2471+ using __cond_res =
2472+ decltype (false ? _VSTD::declval<_Xp(&)()>()() : _VSTD::declval<_Yp(&)()>()());
2473+
2474+ // Let `XREF(A)` denote a unary alias template `T` such that `T<U>` denotes the same type as `U`
2475+ // with the addition of `A`'s cv and reference qualifiers, for a non-reference cv-unqualified type
2476+ // `U`.
2477+ // [Note: `XREF(A)` is `__xref<A>::template __apply`]
2478+ template <class _Tp >
2479+ struct __xref {
2480+ template <class _Up >
2481+ using __apply = __copy_cvref_t <_Tp, _Up>;
2482+ };
2483+
2484+ // Given types `A` and `B`, let `X` be `remove_reference_t<A>`, let `Y` be `remove_reference_t<B>`,
2485+ // and let `COMMON-REF(A, B)` be:
2486+ template <class _Ap , class _Bp , class _Xp = remove_reference_t <_Ap>, class _Yp = remove_reference_t <_Bp>>
2487+ struct __common_ref ;
2488+
2489+ template <class _Xp , class _Yp >
2490+ using __common_ref_t = typename __common_ref<_Xp, _Yp>::__type;
2491+
2492+ template <class _Xp , class _Yp >
2493+ using __cv_cond_res = __cond_res<__copy_cv_t <_Xp, _Yp>&, __copy_cv_t <_Yp, _Xp>&>;
2494+
2495+
2496+ // If `A` and `B` are both lvalue reference types, `COMMON-REF(A, B)` is
2497+ // `COND-RES(COPYCV(X, Y) &, COPYCV(Y, X) &)` if that type exists and is a reference type.
2498+ template <class _Ap , class _Bp , class _Xp , class _Yp >
2499+ requires requires { typename __cv_cond_res<_Xp, _Yp>; } && is_reference_v<__cv_cond_res<_Xp, _Yp>>
2500+ struct __common_ref <_Ap&, _Bp&, _Xp, _Yp>
2501+ {
2502+ using __type = __cv_cond_res<_Xp, _Yp>;
2503+ };
2504+
2505+ // Otherwise, let `C` be `remove_reference_t<COMMON-REF(X&, Y&)>&&`....
2506+ template <class _Xp , class _Yp >
2507+ using __common_ref_C = remove_reference_t <__common_ref_t <_Xp&, _Yp&>>&&;
2508+
2509+
2510+ // .... If `A` and `B` are both rvalue reference types, `C` is well-formed, and
2511+ // `is_convertible_v<A, C> && is_convertible_v<B, C>` is `true`, then `COMMON-REF(A, B)` is `C`.
2512+ template <class _Ap , class _Bp , class _Xp , class _Yp >
2513+ requires
2514+ requires { typename __common_ref_C<_Xp, _Yp>; } &&
2515+ is_convertible_v<_Ap&&, __common_ref_C<_Xp, _Yp>> &&
2516+ is_convertible_v<_Bp&&, __common_ref_C<_Xp, _Yp>>
2517+ struct __common_ref <_Ap&&, _Bp&&, _Xp, _Yp>
2518+ {
2519+ using __type = __common_ref_C<_Xp, _Yp>;
2520+ };
2521+
2522+ // Otherwise, let `D` be `COMMON-REF(const X&, Y&)`....
2523+ template <class _Tp , class _Up >
2524+ using __common_ref_D = __common_ref_t <const _Tp&, _Up&>;
2525+
2526+ // ... If `A` is an rvalue reference and `B` is an lvalue reference and `D` is well-formed and
2527+ // `is_convertible_v<A, D>` is `true`, then `COMMON-REF(A, B)` is `D`.
2528+ template <class _Ap , class _Bp , class _Xp , class _Yp >
2529+ requires requires { typename __common_ref_D<_Xp, _Yp>; } &&
2530+ is_convertible_v<_Ap&&, __common_ref_D<_Xp, _Yp>>
2531+ struct __common_ref <_Ap&&, _Bp&, _Xp, _Yp>
2532+ {
2533+ using __type = __common_ref_D<_Xp, _Yp>;
2534+ };
2535+
2536+ // Otherwise, if `A` is an lvalue reference and `B` is an rvalue reference, then
2537+ // `COMMON-REF(A, B)` is `COMMON-REF(B, A)`.
2538+ template <class _Ap , class _Bp , class _Xp , class _Yp >
2539+ struct __common_ref <_Ap&, _Bp&&, _Xp, _Yp> : __common_ref<_Bp&&, _Ap&> {};
2540+
2541+ // Otherwise, `COMMON-REF(A, B)` is ill-formed.
2542+ template <class _Ap , class _Bp , class _Xp , class _Yp >
2543+ struct __common_ref {};
2544+
2545+ // Note C: For the common_reference trait applied to a parameter pack [...]
2546+
2547+ template <class ...>
2548+ struct common_reference ;
2549+
2550+ template <class ... _Types>
2551+ using common_reference_t = typename common_reference<_Types...>::type;
2552+
2553+ // bullet 1 - sizeof...(T) == 0
2554+ template <>
2555+ struct common_reference <> {};
2556+
2557+ // bullet 2 - sizeof...(T) == 1
2558+ template <class _Tp >
2559+ struct common_reference <_Tp>
2560+ {
2561+ using type = _Tp;
2562+ };
2563+
2564+ // bullet 3 - sizeof...(T) == 2
2565+ template <class _Tp , class _Up > struct __common_reference_sub_bullet3 ;
2566+ template <class _Tp , class _Up > struct __common_reference_sub_bullet2 : __common_reference_sub_bullet3<_Tp, _Up> {};
2567+ template <class _Tp , class _Up > struct __common_reference_sub_bullet1 : __common_reference_sub_bullet2<_Tp, _Up> {};
2568+
2569+ // sub-bullet 1 - If `T1` and `T2` are reference types and `COMMON-REF(T1, T2)` is well-formed, then
2570+ // the member typedef type denotes that type.
2571+ template <class _Tp , class _Up > struct common_reference <_Tp, _Up> : __common_reference_sub_bullet1<_Tp, _Up> {};
2572+
2573+ template <class _Tp , class _Up >
2574+ requires is_reference_v<_Tp> && is_reference_v<_Up> && requires { typename __common_ref_t <_Tp, _Up>; }
2575+ struct __common_reference_sub_bullet1 <_Tp, _Up>
2576+ {
2577+ using type = __common_ref_t <_Tp, _Up>;
2578+ };
2579+
2580+ // sub-bullet 2 - Otherwise, if `basic_common_reference<remove_cvref_t<T1>, remove_cvref_t<T2>, XREF(T1), XREF(T2)>::type`
2581+ // is well-formed, then the member typedef type denotes that type.
2582+ template <class , class , template <class > class , template <class > class > struct basic_common_reference {};
2583+
2584+ template <class _Tp , class _Up >
2585+ using __basic_common_reference_t = typename basic_common_reference<
2586+ remove_cvref_t <_Tp>, remove_cvref_t <_Up>,
2587+ __xref<_Tp>::template __apply, __xref<_Up>::template __apply>::type;
2588+
2589+ template <class _Tp , class _Up >
2590+ requires requires { typename __basic_common_reference_t <_Tp, _Up>; }
2591+ struct __common_reference_sub_bullet2 <_Tp, _Up>
2592+ {
2593+ using type = __basic_common_reference_t <_Tp, _Up>;
2594+ };
2595+
2596+ // sub-bullet 3 - Otherwise, if `COND-RES(T1, T2)` is well-formed, then the member typedef type
2597+ // denotes that type.
2598+ template <class _Tp , class _Up >
2599+ requires requires { typename __cond_res<_Tp, _Up>; }
2600+ struct __common_reference_sub_bullet3 <_Tp, _Up>
2601+ {
2602+ using type = __cond_res<_Tp, _Up>;
2603+ };
2604+
2605+
2606+ // sub-bullet 4 & 5 - Otherwise, if `common_type_t<T1, T2>` is well-formed, then the member typedef
2607+ // type denotes that type.
2608+ // - Otherwise, there shall be no member type.
2609+ template <class _Tp , class _Up > struct __common_reference_sub_bullet3 : common_type<_Tp, _Up> {};
2610+
2611+ // bullet 4 - If there is such a type `C`, the member typedef type shall denote the same type, if
2612+ // any, as `common_reference_t<C, Rest...>`.
2613+ template <class _Tp , class _Up , class _Vp , class ... _Rest>
2614+ requires requires { typename common_reference_t <_Tp, _Up>; }
2615+ struct common_reference <_Tp, _Up, _Vp, _Rest...>
2616+ : common_reference<common_reference_t <_Tp, _Up>, _Vp, _Rest...>
2617+ {};
2618+
2619+ // bullet 5 - Otherwise, there shall be no member type.
2620+ template <class ...> struct common_reference {};
2621+
2622+ #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
2623+
24142624// is_assignable
24152625
24162626template <typename , typename _Tp> struct __select_2nd { typedef _LIBCPP_NODEBUG_TYPE _Tp type; };
0 commit comments