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..cd40abc7795 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,10 @@ 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 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> {}; @@ -1376,37 +1379,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 +1475,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. +// (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 +2095,37 @@ 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 _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 (_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 (_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>; +}; +#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..472a2f77b74 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: @@ -1611,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 8ecc5122dad..c855ff0b012 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>); @@ -1362,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&>); @@ -1421,7 +1424,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 +1432,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 +1453,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 +1462,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 +1474,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 +1488,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 +1498,16 @@ 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>); + +#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 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..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,6 +448,34 @@ STATIC_ASSERT(__cpp_lib_clamp == 201603L); #endif #endif +#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 +#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 + +#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 +#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