From cee29fe77b6f3ef748b9b1a3fb408c75f50d7ace Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Wed, 1 Mar 2023 01:36:05 +0800 Subject: [PATCH 1/6] Implement P2655R3 --- stl/inc/concepts | 10 -- stl/inc/type_traits | 98 +++++++++++++------ stl/inc/yvals_core.h | 3 + .../tests/VSO_0000000_type_traits/test.cpp | 26 +++-- .../test.compile.pass.cpp | 24 +++++ 5 files changed, 112 insertions(+), 49 deletions(-) diff --git a/stl/inc/concepts b/stl/inc/concepts index 35845c6c674..15845cb6d71 100644 --- a/stl/inc/concepts +++ b/stl/inc/concepts @@ -39,16 +39,6 @@ _EXPORT_STD template concept derived_from = __is_base_of(_Base, _Derived) && __is_convertible_to(const volatile _Derived*, const volatile _Base*); -_EXPORT_STD template -#if !defined(__EDG__) && !defined(__clang__) // TRANSITION, DevCom-1627396 -concept convertible_to = is_convertible_v<_From, _To> -#else // ^^^ workaround / no workaround vvv -concept convertible_to = __is_convertible_to(_From, _To) -#endif // ^^^ no workaround ^^^ - && requires { - static_cast<_To>(_STD declval<_From>()); - }; - template concept _Implicitly_convertible_to = is_convertible_v<_From, _To>; diff --git a/stl/inc/type_traits b/stl/inc/type_traits index 463db6fd760..0805dcf7a7b 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -140,7 +140,7 @@ using add_rvalue_reference_t = typename _Add_reference<_Ty>::_Rvalue; _EXPORT_STD template add_rvalue_reference_t<_Ty> declval() noexcept { - static_assert(_Always_false<_Ty>, "Calling declval is ill-formed, see N4917 22.2.6 [declval]/2."); + static_assert(_Always_false<_Ty>, "Calling declval is ill-formed, see N4928 [declval]/2."); } _EXPORT_STD template @@ -1201,8 +1201,8 @@ using _Conditional_type = decltype(false ? _STD declval<_Ty1>() : _STD declval<_ template struct _Const_lvalue_cond_oper {}; -// N4917 21.3.8.7 [meta.trans.other]/3.3.4 (per the proposed resolution of LWG-3205): "Otherwise, if -// remove_cvref_t denotes a type..." +// N4928 [meta.trans.other]/3.3.4 (per the proposed resolution of LWG-3205): "Otherwise, if remove_cvref_t denotes +// a type..." template struct _Const_lvalue_cond_oper<_Ty1, _Ty2, void_t<_Conditional_type>> { using type = remove_cvref_t<_Conditional_type>; @@ -1279,11 +1279,11 @@ struct _Copy_cv_impl { using _Apply = const volatile _To; }; template -using _Copy_cv = // N4917 21.3.8.7 [meta.trans.other]/2.3 +using _Copy_cv = // N4928 [meta.trans.other]/2.3 typename _Copy_cv_impl<_From>::template _Apply<_To>; template -struct _Add_qualifiers { // _Add_qualifiers::template _Apply is XREF(A) from N4917 21.3.8.7 [meta.trans.other]/2.2 +struct _Add_qualifiers { // _Add_qualifiers::template _Apply is XREF(A) from N4928 [meta.trans.other]/2.2 template using _Apply = _Copy_cv<_Ty1, _Ty2>; }; @@ -1300,7 +1300,7 @@ struct _Add_qualifiers<_Ty1&&> { #if !defined(__EDG__) && !defined(__clang__) // TRANSITION, DevCom-10095944 template -using _Cond_res_if_right = // N4917 21.3.8.7 [meta.trans.other]/2.4 +using _Cond_res_if_right = // N4928 [meta.trans.other]/2.4 decltype(false ? _Returns_exactly<_Ty1>() : _Returns_exactly<_Ty2>()); template @@ -1322,7 +1322,7 @@ template using _Cond_res = typename _Cond_res_workaround<_Ty1, _Ty2>::type; #else // ^^^ workaround / no workaround vvv template -using _Cond_res = // N4917 21.3.8.7 [meta.trans.other]/2.4 +using _Cond_res = // N4928 [meta.trans.other]/2.4 decltype(false ? _Returns_exactly<_Ty1>() : _Returns_exactly<_Ty2>()); #endif // ^^^ no workaround ^^^ @@ -1332,30 +1332,30 @@ struct common_reference; _EXPORT_STD template using common_reference_t = typename common_reference<_Types...>::type; -// N4917 21.3.8.7 [meta.trans.other]/5.1: "If sizeof...(T) is zero ..." +// N4928 [meta.trans.other]/5.1: "If sizeof...(T) is zero ..." template <> struct common_reference<> {}; -// N4917 21.3.8.7 [meta.trans.other]/5.2: "...if sizeof...(T) is one ..." +// N4928 [meta.trans.other]/5.2: "...if sizeof...(T) is one ..." template struct common_reference<_Ty> { using type = _Ty; }; -// N4917 21.3.8.7 [meta.trans.other]/5.3: "...if sizeof...(T) is two..." +// N4928 [meta.trans.other]/5.3: "...if sizeof...(T) is two..." -// N4917 21.3.8.7 [meta.trans.other]/5.3.4: "if common_type_t is well-formed..." -// N4917 21.3.8.7 [meta.trans.other]/5.3.5: "Otherwise, there shall be no member type." +// N4928 [meta.trans.other]/5.3.4: "if common_type_t is well-formed..." +// N4928 [meta.trans.other]/5.3.5: "Otherwise, there shall be no member type." template struct _Common_reference2C : common_type<_Ty1, _Ty2> {}; -// N4917 21.3.8.7 [meta.trans.other]/5.3.3: "if COND_RES(T1, T2) is well-formed..." +// N4928 [meta.trans.other]/5.3.3: "if COND_RES(T1, T2) is well-formed..." template struct _Common_reference2C<_Ty1, _Ty2, void_t<_Cond_res<_Ty1, _Ty2>>> { using type = _Cond_res<_Ty1, _Ty2>; }; -// N4917 21.3.8.7 [meta.trans.other]/5.3.2: "if basic_common_reference<[...]>::type is well-formed..." +// N4928 [meta.trans.other]/5.3.2: "if basic_common_reference<[...]>::type is well-formed..." template using _Basic_specialization = typename basic_common_reference, remove_cvref_t<_Ty2>, _Add_qualifiers<_Ty1>::template _Apply, _Add_qualifiers<_Ty2>::template _Apply>::type; @@ -1368,7 +1368,7 @@ struct _Common_reference2B<_Ty1, _Ty2, void_t<_Basic_specialization<_Ty1, _Ty2>> using type = _Basic_specialization<_Ty1, _Ty2>; }; -// N4917 21.3.8.7 [meta.trans.other]/5.3.1: "If T1 and T2 are reference types and COMMON_REF(T1, T2) is well-formed..." +// N4928 [meta.trans.other]/5.3.1: "If T1 and T2 are reference types and COMMON_REF(T1, T2) is well-formed..." template struct _Common_reference2A : _Common_reference2B<_Ty1, _Ty2> {}; @@ -1376,37 +1376,48 @@ template enable_if_t, int> = 0> using _LL_common_ref = _Result; +template +struct _Common_reference2AX {}; + template -struct _Common_reference2A<_Ty1&, _Ty2&, void_t<_LL_common_ref<_Ty1, _Ty2>>> { - using type = _LL_common_ref<_Ty1, _Ty2>; // "both lvalues" case from N4917 21.3.8.7 [meta.trans.other]/2.5 +struct _Common_reference2AX<_Ty1&, _Ty2&, void_t<_LL_common_ref<_Ty1, _Ty2>>> { + using type = _LL_common_ref<_Ty1, _Ty2>; // "both lvalues" case from N4928 [meta.trans.other]/2.5 }; template -struct _Common_reference2A<_Ty1&&, _Ty2&, enable_if_t>>> { - using type = - _LL_common_ref; // "rvalue and lvalue" case from N4917 21.3.8.7 [meta.trans.other]/2.7 +struct _Common_reference2AX<_Ty1&&, _Ty2&, enable_if_t>>> { + using type = _LL_common_ref; // "rvalue and lvalue" case from N4928 [meta.trans.other]/2.7 }; template -struct _Common_reference2A<_Ty1&, _Ty2&&, enable_if_t>>> { - using type = - _LL_common_ref; // "lvalue and rvalue" case from N4917 21.3.8.7 [meta.trans.other]/2.8 +struct _Common_reference2AX<_Ty1&, _Ty2&&, enable_if_t>>> { + using type = _LL_common_ref; // "lvalue and rvalue" case from N4928 [meta.trans.other]/2.8 }; template using _RR_common_ref = remove_reference_t<_LL_common_ref<_Ty1, _Ty2>>&&; template -struct _Common_reference2A<_Ty1&&, _Ty2&&, +struct _Common_reference2AX<_Ty1&&, _Ty2&&, enable_if_t> && is_convertible_v<_Ty2&&, _RR_common_ref<_Ty1, _Ty2>>>> { - using type = _RR_common_ref<_Ty1, _Ty2>; // "both rvalues" case from N4917 21.3.8.7 [meta.trans.other]/2.6 + using type = _RR_common_ref<_Ty1, _Ty2>; // "both rvalues" case from N4928 [meta.trans.other]/2.6 +}; + +template +using _Common_ref_2AX_t = typename _Common_reference2AX<_Ty1, _Ty2>::type; + +template +struct _Common_reference2A<_Ty1, _Ty2, + enable_if_t, add_pointer_t<_Common_ref_2AX_t<_Ty1, _Ty2>>> + && is_convertible_v, add_pointer_t<_Common_ref_2AX_t<_Ty1, _Ty2>>>>> { + using type = _Common_ref_2AX_t<_Ty1, _Ty2>; }; template struct common_reference<_Ty1, _Ty2> : _Common_reference2A<_Ty1, _Ty2> {}; -// N4917 21.3.8.7 [meta.trans.other]/5.4: "if sizeof...(T) is greater than two..." +// N4928 [meta.trans.other]/5.4: "if sizeof...(T) is greater than two..." template struct _Fold_common_reference {}; template @@ -1461,9 +1472,8 @@ _EXPORT_STD template class reference_wrapper; // std::invoke isn't constexpr in C++17, and normally implementers are forbidden from "strengthening" constexpr -// (WG21-N4917 16.4.6.7 [constexpr.functions]/1), yet both std::apply and std::visit are required to be constexpr and -// have invoke-like behavior. As a result, we've chosen to apply the part of P1065R2 resolving LWG-2894 as a defect -// report. +// (WG21-N4928 [constexpr.functions]/1), yet both std::apply and std::visit are required to be constexpr and have +// invoke-like behavior. As a result, we've chosen to apply the part of P1065R2 resolving LWG-2894 as a defect report. enum class _Invoker_strategy { _Functor, @@ -2082,6 +2092,36 @@ struct _Is_trivially_swappable : bool_constant<_Is_trivially_swappable_v<_Ty>> { // true_type if and only if it is valid to swap two _Ty lvalues by exchanging object representations. }; +#ifdef __cpp_lib_concepts // TRANSITION, GH-395 +_EXPORT_STD template +concept convertible_to = +#if !defined(__EDG__) && !defined(__clang__) // TRANSITION, DevCom-1627396 + is_convertible_v<_From, _To> +#else // ^^^ workaround / no workaround vvv + __is_convertible_to(_From, _To) +#endif // ^^^ no workaround ^^^ + && requires { static_cast<_To>(_STD declval<_From>()); }; + +template +concept _Has_ref_wrap_common_reference = _Is_specialization_v<_RefWrap, reference_wrapper> + && requires { typename common_reference_t; } + && convertible_to<_RefWrapQ, common_reference_t>; + +template class _RefWrapQual, template class _TyQual> + requires(_Has_ref_wrap_common_reference<_RefWrap, _Ty, _RefWrapQual<_RefWrap>, _TyQual<_Ty>> + && !_Has_ref_wrap_common_reference<_Ty, _RefWrap, _TyQual<_Ty>, _RefWrapQual<_RefWrap>>) +struct basic_common_reference<_RefWrap, _Ty, _RefWrapQual, _TyQual> { + using type = common_reference_t>; +}; + +template class _TyQual, template class _RefWrapQual> + requires(_Has_ref_wrap_common_reference<_RefWrap, _Ty, _RefWrapQual<_RefWrap>, _TyQual<_Ty>> + && !_Has_ref_wrap_common_reference<_Ty, _RefWrap, _TyQual<_Ty>, _RefWrapQual<_RefWrap>>) +struct basic_common_reference<_Ty, _RefWrap, _TyQual, _RefWrapQual> { + using type = common_reference_t>; +}; +#endif // __cpp_lib_concepts + #define _BITMASK_OPS(_MAYBE_EXPORT, _BITMASK) \ _MAYBE_EXPORT _NODISCARD constexpr _BITMASK operator&(_BITMASK _Left, _BITMASK _Right) noexcept { \ using _IntTy = _STD underlying_type_t<_BITMASK>; \ diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 0837c68a0e4..bb218a09ef4 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -288,6 +288,7 @@ // P2588R3 barrier's Phase Completion Guarantees // P2602R2 Poison Pills Are Too Toxic // P2609R3 Relaxing Ranges Just A Smidge +// P2655R3 common_reference_t Of reference_wrapper Should Be A Reference Type // P2711R1 Making Multi-Param Constructors Of Views explicit // _HAS_CXX20 indirectly controls: @@ -1597,6 +1598,8 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #ifdef __cpp_lib_concepts #define __cpp_lib_algorithm_iterator_requirements 202207L +#define __cpp_lib_common_reference 202302L +#define __cpp_lib_common_reference_wrapper 202302L #endif // __cpp_lib_concepts #define __cpp_lib_assume_aligned 201811L diff --git a/tests/std/tests/VSO_0000000_type_traits/test.cpp b/tests/std/tests/VSO_0000000_type_traits/test.cpp index 8ecc5122dad..9ac227f3362 100644 --- a/tests/std/tests/VSO_0000000_type_traits/test.cpp +++ b/tests/std/tests/VSO_0000000_type_traits/test.cpp @@ -5,6 +5,7 @@ #define _SILENCE_CXX17_IS_LITERAL_TYPE_DEPRECATION_WARNING #define _SILENCE_CXX20_IS_POD_DEPRECATION_WARNING +#include #include #include @@ -1340,11 +1341,11 @@ template class TQual, template , tuple_ish, TQual, UQual> : tuple_ish_helper...>, tuple_ish...>> {}; -// N4810 [meta.trans.other]/5.1: If sizeof...(T) is zero, there shall be no member type. +// N4928 [meta.trans.other]/5.1: If sizeof...(T) is zero, there shall be no member type. STATIC_ASSERT(!is_trait>); -// N4810 [meta.trans.other]/5.2: Otherwise, if sizeof...(T) is one, let T0 denote the sole type in the pack T. The +// N4928 [meta.trans.other]/5.2: Otherwise, if sizeof...(T) is one, let T0 denote the sole type in the pack T. The // member typedef type shall denote the same type as T0. STATIC_ASSERT(is_same_v, void>); STATIC_ASSERT(is_same_v, int>); @@ -1421,7 +1422,7 @@ constexpr bool strict_only_common_reference_cases() { STATIC_ASSERT(strict_only_common_reference_cases()); -// N4810 [meta.trans.other]/5.3.2: Otherwise, if basic_common_reference, remove_cvref_t, +// N4928 [meta.trans.other]/5.3.2: Otherwise, if basic_common_reference, remove_cvref_t, // XREF(T1), XREF(T2)>::type is well-formed, then the member typedef type denotes that type. STATIC_ASSERT(is_same_v const&, tuple_ish>, tuple_ish>); @@ -1429,7 +1430,7 @@ STATIC_ASSERT(is_same_v volatile&, tupl tuple_ish const volatile&>); -// N4810 [meta.trans.other]/5.3.3: Otherwise, if COND_RES(T1, T2) is well-formed, then the member typedef type +// N4928 [meta.trans.other]/5.3.3: Otherwise, if COND_RES(T1, T2) is well-formed, then the member typedef type // denotes that type. STATIC_ASSERT(is_same_v, void>); STATIC_ASSERT(is_same_v, void>); @@ -1450,7 +1451,7 @@ STATIC_ASSERT(is_same_v, int*>); STATIC_ASSERT(is_same_v>, converts_from>); -// N4810 [meta.trans.other]/5.3.4: Otherwise, if common_type_t is well-formed, then the member typedef type +// N4928 [meta.trans.other]/5.3.4: Otherwise, if common_type_t is well-formed, then the member typedef type // denotes that type. STATIC_ASSERT(is_same_v&, interconvertible<1> const&>, interconvertible<2>>); @@ -1459,7 +1460,7 @@ STATIC_ASSERT(is_same_v const&, move_ STATIC_ASSERT(is_same_v>, move_only>); -// N4810 [meta.trans.other]/5.3.5: Otherwise, there shall be no member type. +// N4928 [meta.trans.other]/5.3.5: Otherwise, there shall be no member type. STATIC_ASSERT(!is_trait volatile&, tuple_ish const&>>); STATIC_ASSERT(!is_trait>); @@ -1471,10 +1472,10 @@ STATIC_ASSERT(!is_trait>); STATIC_ASSERT(!is_trait>); -// N4810 [meta.trans.other]/5.4: Otherwise, if sizeof...(T) is greater than two, let T1, T2, and Rest, respectively, +// N4928 [meta.trans.other]/5.4: Otherwise, if sizeof...(T) is greater than two, let T1, T2, and Rest, respectively, // denote the first, second, and (pack of) remaining types comprising T. Let C be the type // common_reference_t. Then: -// N4810 [meta.trans.other]/5.4.1: If there is such a type C, the member typedef type shall denote the same type, if +// N4928 [meta.trans.other]/5.4.1: If there is such a type C, the member typedef type shall denote the same type, if // any, as common_reference_t. STATIC_ASSERT(is_same_v, int>); STATIC_ASSERT(is_same_v, int const volatile&>); @@ -1485,7 +1486,7 @@ STATIC_ASSERT( is_same_v, simple_base&>); -// N4810 [meta.trans.other]/5.4.2: Otherwise, there shall be no member type. +// N4928 [meta.trans.other]/5.4.2: Otherwise, there shall be no member type. STATIC_ASSERT(!is_trait>); template @@ -1495,9 +1496,14 @@ struct bad_reference_wrapper { operator T&() const; }; -// N4810 [meta.trans.other]/3.3.4 (per the proposed resolution of LWG-3205): Otherwise, if +// N4928 [meta.trans.other]/3.3.4 (per the proposed resolution of LWG-3205): Otherwise, if // remove_cvref_t() : declval())> // denotes a type, let C denote that type. STATIC_ASSERT(is_same_v>, int>); STATIC_ASSERT(is_same_v, double>, double>); + +// P2655R3 common_reference_t Of reference_wrapper Should Be A Reference Type +STATIC_ASSERT(is_same_v>, int&>); +STATIC_ASSERT(is_same_v&>, int&>); +STATIC_ASSERT(is_same_v&>, int&>); #endif // _HAS_CXX20 diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index db550d2fdb5..5d6a7bf4aef 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -40,6 +40,30 @@ STATIC_ASSERT(__cpp_lib_algorithm_iterator_requirements == 202207L); #ifdef __cpp_lib_algorithm_iterator_requirements #error __cpp_lib_algorithm_iterator_requirements is defined #endif + +#ifndef __cpp_lib_common_reference +#error __cpp_lib_common_reference is not defined +#elif __cpp_lib_common_reference != 202302L +#error __cpp_lib_common_reference is not 202302L +#else +STATIC_ASSERT(__cpp_lib_common_reference == 202302L); +#endif +#else +#ifdef __cpp_lib_common_reference +#error __cpp_lib_common_reference is defined +#endif + +#ifndef __cpp_lib_common_reference_wrapper +#error __cpp_lib_common_reference_wrapper is not defined +#elif __cpp_lib_common_reference_wrapper != 202302L +#error __cpp_lib_common_reference_wrapper is not 202302L +#else +STATIC_ASSERT(__cpp_lib_common_reference_wrapper == 202302L); +#endif +#else +#ifdef __cpp_lib_common_reference_wrapper +#error __cpp_lib_common_reference_wrapper is defined +#endif #endif #if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 From 3d0a9cfd8cdbab3166b53f648c29fa16576f7fd0 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Wed, 1 Mar 2023 01:53:48 +0800 Subject: [PATCH 2/6] Clang-format --- stl/inc/type_traits | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/type_traits b/stl/inc/type_traits index 0805dcf7a7b..48053e60f7a 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -2108,15 +2108,15 @@ concept _Has_ref_wrap_common_reference = _Is_specialization_v<_RefWrap, referenc && convertible_to<_RefWrapQ, common_reference_t>; template class _RefWrapQual, template class _TyQual> - requires(_Has_ref_wrap_common_reference<_RefWrap, _Ty, _RefWrapQual<_RefWrap>, _TyQual<_Ty>> - && !_Has_ref_wrap_common_reference<_Ty, _RefWrap, _TyQual<_Ty>, _RefWrapQual<_RefWrap>>) + requires (_Has_ref_wrap_common_reference<_RefWrap, _Ty, _RefWrapQual<_RefWrap>, _TyQual<_Ty>> + && !_Has_ref_wrap_common_reference<_Ty, _RefWrap, _TyQual<_Ty>, _RefWrapQual<_RefWrap>>) struct basic_common_reference<_RefWrap, _Ty, _RefWrapQual, _TyQual> { using type = common_reference_t>; }; template class _TyQual, template class _RefWrapQual> - requires(_Has_ref_wrap_common_reference<_RefWrap, _Ty, _RefWrapQual<_RefWrap>, _TyQual<_Ty>> - && !_Has_ref_wrap_common_reference<_Ty, _RefWrap, _TyQual<_Ty>, _RefWrapQual<_RefWrap>>) + requires (_Has_ref_wrap_common_reference<_RefWrap, _Ty, _RefWrapQual<_RefWrap>, _TyQual<_Ty>> + && !_Has_ref_wrap_common_reference<_Ty, _RefWrap, _TyQual<_Ty>, _RefWrapQual<_RefWrap>>) struct basic_common_reference<_Ty, _RefWrap, _TyQual, _RefWrapQual> { using type = common_reference_t>; }; From ef611591a144d44a3844ba7d561869c3d6a790f4 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Wed, 1 Mar 2023 02:21:30 +0800 Subject: [PATCH 3/6] Fix the test file --- .../test.compile.pass.cpp | 54 ++++++++++--------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 5d6a7bf4aef..d701bd90bc1 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -28,7 +28,7 @@ STATIC_ASSERT(__cpp_lib_adaptor_iterator_pair_constructor == 202106L); STATIC_ASSERT(__cpp_lib_addressof_constexpr == 201603L); #endif -#if _HAS_CXX20 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 +#ifdef __cpp_lib_concepts #ifndef __cpp_lib_algorithm_iterator_requirements #error __cpp_lib_algorithm_iterator_requirements is not defined #elif __cpp_lib_algorithm_iterator_requirements != 202207L @@ -40,30 +40,6 @@ STATIC_ASSERT(__cpp_lib_algorithm_iterator_requirements == 202207L); #ifdef __cpp_lib_algorithm_iterator_requirements #error __cpp_lib_algorithm_iterator_requirements is defined #endif - -#ifndef __cpp_lib_common_reference -#error __cpp_lib_common_reference is not defined -#elif __cpp_lib_common_reference != 202302L -#error __cpp_lib_common_reference is not 202302L -#else -STATIC_ASSERT(__cpp_lib_common_reference == 202302L); -#endif -#else -#ifdef __cpp_lib_common_reference -#error __cpp_lib_common_reference is defined -#endif - -#ifndef __cpp_lib_common_reference_wrapper -#error __cpp_lib_common_reference_wrapper is not defined -#elif __cpp_lib_common_reference_wrapper != 202302L -#error __cpp_lib_common_reference_wrapper is not 202302L -#else -STATIC_ASSERT(__cpp_lib_common_reference_wrapper == 202302L); -#endif -#else -#ifdef __cpp_lib_common_reference_wrapper -#error __cpp_lib_common_reference_wrapper is defined -#endif #endif #if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 @@ -472,6 +448,34 @@ STATIC_ASSERT(__cpp_lib_clamp == 201603L); #endif #endif +#ifdef __cpp_lib_concepts +#ifndef __cpp_lib_common_reference +#error __cpp_lib_common_reference is not defined +#elif __cpp_lib_common_reference != 202302L +#error __cpp_lib_common_reference is not 202302L +#else +STATIC_ASSERT(__cpp_lib_common_reference == 202302L); +#endif +#else +#ifdef __cpp_lib_common_reference +#error __cpp_lib_common_reference is defined +#endif +#endif + +#ifdef __cpp_lib_concepts +#ifndef __cpp_lib_common_reference_wrapper +#error __cpp_lib_common_reference_wrapper is not defined +#elif __cpp_lib_common_reference_wrapper != 202302L +#error __cpp_lib_common_reference_wrapper is not 202302L +#else +STATIC_ASSERT(__cpp_lib_common_reference_wrapper == 202302L); +#endif +#else +#ifdef __cpp_lib_common_reference_wrapper +#error __cpp_lib_common_reference_wrapper is defined +#endif +#endif + #ifndef __cpp_lib_complex_udls #error __cpp_lib_complex_udls is not defined #elif __cpp_lib_complex_udls != 201309L From 94895f30aebc45b7378a6e0d4adcf20a82ebce64 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Wed, 1 Mar 2023 07:12:42 +0800 Subject: [PATCH 4/6] Consider EDG --- tests/std/tests/VSO_0000000_type_traits/test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/std/tests/VSO_0000000_type_traits/test.cpp b/tests/std/tests/VSO_0000000_type_traits/test.cpp index 9ac227f3362..b10217ee860 100644 --- a/tests/std/tests/VSO_0000000_type_traits/test.cpp +++ b/tests/std/tests/VSO_0000000_type_traits/test.cpp @@ -1502,8 +1502,10 @@ struct bad_reference_wrapper { STATIC_ASSERT(is_same_v>, int>); STATIC_ASSERT(is_same_v, double>, double>); +#ifdef __cpp_lib_concepts // TRANSITION, GH-395 // P2655R3 common_reference_t Of reference_wrapper Should Be A Reference Type STATIC_ASSERT(is_same_v>, int&>); STATIC_ASSERT(is_same_v&>, int&>); STATIC_ASSERT(is_same_v&>, int&>); +#endif // __cpp_lib_concepts #endif // _HAS_CXX20 From 5e6c5727c10524ef3dfd4a4b36541f40e1f6b386 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Wed, 1 Mar 2023 07:12:57 +0800 Subject: [PATCH 5/6] Revert unintended modifications --- stl/inc/type_traits | 15 ++++++++------- .../test.compile.pass.cpp | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/stl/inc/type_traits b/stl/inc/type_traits index 48053e60f7a..f167c16a0af 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -2103,20 +2103,21 @@ concept convertible_to = && requires { static_cast<_To>(_STD declval<_From>()); }; template -concept _Has_ref_wrap_common_reference = _Is_specialization_v<_RefWrap, reference_wrapper> - && requires { typename common_reference_t; } - && convertible_to<_RefWrapQ, common_reference_t>; +concept _Ref_wrap_common_reference_exists_with = + _Is_specialization_v<_RefWrap, reference_wrapper> + && requires { typename common_reference_t; } + && convertible_to<_RefWrapQ, common_reference_t>; template class _RefWrapQual, template class _TyQual> - requires (_Has_ref_wrap_common_reference<_RefWrap, _Ty, _RefWrapQual<_RefWrap>, _TyQual<_Ty>> - && !_Has_ref_wrap_common_reference<_Ty, _RefWrap, _TyQual<_Ty>, _RefWrapQual<_RefWrap>>) + requires (_Ref_wrap_common_reference_exists_with<_RefWrap, _Ty, _RefWrapQual<_RefWrap>, _TyQual<_Ty>> + && !_Ref_wrap_common_reference_exists_with<_Ty, _RefWrap, _TyQual<_Ty>, _RefWrapQual<_RefWrap>>) struct basic_common_reference<_RefWrap, _Ty, _RefWrapQual, _TyQual> { using type = common_reference_t>; }; template class _TyQual, template class _RefWrapQual> - requires (_Has_ref_wrap_common_reference<_RefWrap, _Ty, _RefWrapQual<_RefWrap>, _TyQual<_Ty>> - && !_Has_ref_wrap_common_reference<_Ty, _RefWrap, _TyQual<_Ty>, _RefWrapQual<_RefWrap>>) + requires (_Ref_wrap_common_reference_exists_with<_RefWrap, _Ty, _RefWrapQual<_RefWrap>, _TyQual<_Ty>> + && !_Ref_wrap_common_reference_exists_with<_Ty, _RefWrap, _TyQual<_Ty>, _RefWrapQual<_RefWrap>>) struct basic_common_reference<_Ty, _RefWrap, _TyQual, _RefWrapQual> { using type = common_reference_t>; }; diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index d701bd90bc1..9635e1165ac 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -28,7 +28,7 @@ STATIC_ASSERT(__cpp_lib_adaptor_iterator_pair_constructor == 202106L); STATIC_ASSERT(__cpp_lib_addressof_constexpr == 201603L); #endif -#ifdef __cpp_lib_concepts +#if _HAS_CXX20 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 #ifndef __cpp_lib_algorithm_iterator_requirements #error __cpp_lib_algorithm_iterator_requirements is not defined #elif __cpp_lib_algorithm_iterator_requirements != 202207L From 9bb9ea95ef33e7ccb3405de612de4dee062be863 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 2 Mar 2023 06:39:31 -0800 Subject: [PATCH 6/6] Code review feedback. --- stl/inc/type_traits | 7 ++-- stl/inc/yvals_core.h | 36 ++++++++++--------- .../tests/VSO_0000000_type_traits/test.cpp | 6 ++-- .../test.compile.pass.cpp | 4 +-- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/stl/inc/type_traits b/stl/inc/type_traits index f167c16a0af..cd40abc7795 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -1368,7 +1368,10 @@ struct _Common_reference2B<_Ty1, _Ty2, void_t<_Basic_specialization<_Ty1, _Ty2>> using type = _Basic_specialization<_Ty1, _Ty2>; }; -// N4928 [meta.trans.other]/5.3.1: "If T1 and T2 are reference types and COMMON_REF(T1, T2) is well-formed..." +// N4928 [meta.trans.other]/5.3.1 as updated by P2655R3 (TRANSITION, cite new WP here): +// "Let R be COMMON-REF(T1, T2). If T1 and T2 are reference types, R is well-formed, and +// is_convertible_v, add_pointer_t> && is_convertible_v, add_pointer_t> +// is true, then the member typedef type denotes R." template struct _Common_reference2A : _Common_reference2B<_Ty1, _Ty2> {}; @@ -1472,7 +1475,7 @@ _EXPORT_STD template class reference_wrapper; // std::invoke isn't constexpr in C++17, and normally implementers are forbidden from "strengthening" constexpr -// (WG21-N4928 [constexpr.functions]/1), yet both std::apply and std::visit are required to be constexpr and have +// (N4928 [constexpr.functions]/1), yet both std::apply and std::visit are required to be constexpr and have // invoke-like behavior. As a result, we've chosen to apply the part of P1065R2 resolving LWG-2894 as a defect report. enum class _Invoker_strategy { diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index bb218a09ef4..472a2f77b74 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1598,8 +1598,6 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #ifdef __cpp_lib_concepts #define __cpp_lib_algorithm_iterator_requirements 202207L -#define __cpp_lib_common_reference 202302L -#define __cpp_lib_common_reference_wrapper 202302L #endif // __cpp_lib_concepts #define __cpp_lib_assume_aligned 201811L @@ -1614,20 +1612,26 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_bit_cast 201806L #define __cpp_lib_bitops 201907L #define __cpp_lib_bounded_array_traits 201902L -#define __cpp_lib_constexpr_algorithms 201806L -#define __cpp_lib_constexpr_complex 201711L -#define __cpp_lib_constexpr_dynamic_alloc 201907L -#define __cpp_lib_constexpr_functional 201907L -#define __cpp_lib_constexpr_iterator 201811L -#define __cpp_lib_constexpr_numeric 201911L -#define __cpp_lib_constexpr_string 201907L -#define __cpp_lib_constexpr_string_view 201811L -#define __cpp_lib_constexpr_tuple 201811L -#define __cpp_lib_constexpr_utility 201811L -#define __cpp_lib_constexpr_vector 201907L -#define __cpp_lib_destroying_delete 201806L -#define __cpp_lib_endian 201907L -#define __cpp_lib_erase_if 202002L + +#ifdef __cpp_lib_concepts +#define __cpp_lib_common_reference 202302L +#define __cpp_lib_common_reference_wrapper 202302L +#endif // __cpp_lib_concepts + +#define __cpp_lib_constexpr_algorithms 201806L +#define __cpp_lib_constexpr_complex 201711L +#define __cpp_lib_constexpr_dynamic_alloc 201907L +#define __cpp_lib_constexpr_functional 201907L +#define __cpp_lib_constexpr_iterator 201811L +#define __cpp_lib_constexpr_numeric 201911L +#define __cpp_lib_constexpr_string 201907L +#define __cpp_lib_constexpr_string_view 201811L +#define __cpp_lib_constexpr_tuple 201811L +#define __cpp_lib_constexpr_utility 201811L +#define __cpp_lib_constexpr_vector 201907L +#define __cpp_lib_destroying_delete 201806L +#define __cpp_lib_endian 201907L +#define __cpp_lib_erase_if 202002L #ifdef __cpp_lib_concepts #define __cpp_lib_format 202207L diff --git a/tests/std/tests/VSO_0000000_type_traits/test.cpp b/tests/std/tests/VSO_0000000_type_traits/test.cpp index b10217ee860..c855ff0b012 100644 --- a/tests/std/tests/VSO_0000000_type_traits/test.cpp +++ b/tests/std/tests/VSO_0000000_type_traits/test.cpp @@ -1363,8 +1363,10 @@ STATIC_ASSERT(is_same_v, void() volatile>); STATIC_ASSERT(is_same_v, void() &&>); -// N4810 [meta.trans.other]/5.3.1: If T1 and T2 are reference types and COMMON_REF(T1, T2) is well-formed, then the -// member typedef type denotes that type. +// N4928 [meta.trans.other]/5.3.1 as updated by P2655R3 (TRANSITION, cite new WP here): +// "Let R be COMMON-REF(T1, T2). If T1 and T2 are reference types, R is well-formed, and +// is_convertible_v, add_pointer_t> && is_convertible_v, add_pointer_t> +// is true, then the member typedef type denotes R." STATIC_ASSERT(is_same_v, simple_base&>); STATIC_ASSERT(is_same_v, simple_base const&>); STATIC_ASSERT(is_same_v, simple_base const&>); diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 9635e1165ac..1e545ab4f63 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -448,7 +448,7 @@ STATIC_ASSERT(__cpp_lib_clamp == 201603L); #endif #endif -#ifdef __cpp_lib_concepts +#if _HAS_CXX20 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 #ifndef __cpp_lib_common_reference #error __cpp_lib_common_reference is not defined #elif __cpp_lib_common_reference != 202302L @@ -462,7 +462,7 @@ STATIC_ASSERT(__cpp_lib_common_reference == 202302L); #endif #endif -#ifdef __cpp_lib_concepts +#if _HAS_CXX20 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 #ifndef __cpp_lib_common_reference_wrapper #error __cpp_lib_common_reference_wrapper is not defined #elif __cpp_lib_common_reference_wrapper != 202302L