@@ -2411,6 +2411,216 @@ struct _LIBCPP_TEMPLATE_VIS
2411
2411
template <class ..._Tp> using common_type_t = typename common_type<_Tp...>::type;
2412
2412
#endif
2413
2413
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
+
2414
2624
// is_assignable
2415
2625
2416
2626
template <typename , typename _Tp> struct __select_2nd { typedef _LIBCPP_NODEBUG_TYPE _Tp type; };
0 commit comments