diff --git a/stl/inc/type_traits b/stl/inc/type_traits index f1c2d4acae0..fb09ab24a45 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -78,6 +78,13 @@ struct is_void : bool_constant> {}; template using void_t = void; +template +struct _Identity { + using type = _Ty; +}; +template +using _Identity_t _MSVC_KNOWN_SEMANTICS = typename _Identity<_Ty>::type; + // Type modifiers template struct add_const { // add top-level const qualifier @@ -422,6 +429,22 @@ _MEMBER_CALL_CV_REF_NOEXCEPT(_IS_MEMFUNPTR) _CLASS_DEFINE_CV_REF_NOEXCEPT(_IS_MEMFUNPTR_ELLIPSIS) #undef _IS_MEMFUNPTR_ELLIPSIS +#if _HAS_CXX23 && !defined(__clang__) // TRANSITION, DevCom-10107077, Clang has not implemented Deducing this +#define _IS_MEMFUNPTR_EXPLICIT_THIS_GUIDES(CALL_OPT, CV_OPT, REF_OPT, NOEXCEPT_OPT) \ + template \ + struct _Is_memfunptr<_Ret(CALL_OPT*)(_Self, _Args...) NOEXCEPT_OPT> { \ + using _Bool_type = false_type; \ + using _Guide_type = _Identity<_Ret(_Args...)>; \ + }; + +_NON_MEMBER_CALL(_IS_MEMFUNPTR_EXPLICIT_THIS_GUIDES, , , ) +#ifdef __cpp_noexcept_function_type +_NON_MEMBER_CALL(_IS_MEMFUNPTR_EXPLICIT_THIS_GUIDES, , , noexcept) +#endif // __cpp_noexcept_function_type + +#undef _IS_MEMFUNPTR_EXPLICIT_THIS_GUIDES +#endif // _HAS_CXX23 && !defined(__clang__) + #ifdef __clang__ template _INLINE_VAR constexpr bool is_member_function_pointer_v = __is_member_function_pointer(_Ty); @@ -1382,13 +1405,6 @@ template struct common_reference<_Ty1, _Ty2, _Ty3, _Rest...> : _Fold_common_reference {}; #endif // _HAS_CXX20 -template -struct _Identity { - using type = _Ty; -}; -template -using _Identity_t _MSVC_KNOWN_SEMANTICS = typename _Identity<_Ty>::type; - #if _HAS_CXX20 template struct type_identity { diff --git a/tests/std/tests/Dev11_0535636_functional_overhaul/test.cpp b/tests/std/tests/Dev11_0535636_functional_overhaul/test.cpp index 055718cc9ae..f5236ef8e63 100644 --- a/tests/std/tests/Dev11_0535636_functional_overhaul/test.cpp +++ b/tests/std/tests/Dev11_0535636_functional_overhaul/test.cpp @@ -151,6 +151,10 @@ STATIC_ASSERT(is_member_object_pointer_v); STATIC_ASSERT(!is_member_function_pointer_v); STATIC_ASSERT(!is_member_object_pointer_v); +// Verify that the machinery for LWG-3617 "function/packaged_task deduction guides and deducing this" +// doesn't cause such function pointers to be detected as PMFs. +STATIC_ASSERT(!is_member_function_pointer_v); + // N4594 20.13.7.6 [meta.trans.other]: // Template: diff --git a/tests/std/tests/P0433R2_deduction_guides/test.cpp b/tests/std/tests/P0433R2_deduction_guides/test.cpp index db6aabc226c..3fb58b66819 100644 --- a/tests/std/tests/P0433R2_deduction_guides/test.cpp +++ b/tests/std/tests/P0433R2_deduction_guides/test.cpp @@ -43,6 +43,10 @@ #include #endif // _M_CEE +#if _HAS_CXX23 && !defined(__clang__) // TRANSITION, DevCom-10107077, Clang has not implemented Deducing this +#define HAS_EXPLICIT_THIS_PARAMETER +#endif // _HAS_CXX23 && !defined(__clang__) + using namespace std; template @@ -328,6 +332,90 @@ void test_function_wrapper() { static_assert(is_same_v>); static_assert(is_same_v>); + +#ifdef HAS_EXPLICIT_THIS_PARAMETER + struct ExplicitThisByVal { + void operator()(this ExplicitThisByVal, char) {} + }; + + ExplicitThisByVal explicit_this_by_val_functor{}; + + F f11(explicit_this_by_val_functor); + F f12(as_const(explicit_this_by_val_functor)); + F f13(move(explicit_this_by_val_functor)); + F f14(move(as_const(explicit_this_by_val_functor))); + + static_assert(is_same_v>); + static_assert(is_same_v>); + static_assert(is_same_v>); + static_assert(is_same_v>); + + struct ExplicitThisByRef { + void operator()(this ExplicitThisByRef&, short) {} + }; + + ExplicitThisByRef explicit_this_by_ref_functor{}; + + F f15(explicit_this_by_ref_functor); + + static_assert(is_same_v>); + + struct ExplicitThisByCRef { + void operator()(this const ExplicitThisByCRef&, int) {} + }; + + ExplicitThisByCRef explicit_this_by_cref_functor{}; + + F f16(explicit_this_by_cref_functor); + F f17(as_const(explicit_this_by_cref_functor)); + F f18(move(explicit_this_by_cref_functor)); + F f19(move(as_const(explicit_this_by_cref_functor))); + + static_assert(is_same_v>); + static_assert(is_same_v>); + static_assert(is_same_v>); + static_assert(is_same_v>); + + struct ExplicitThisByConv { + struct That {}; + + operator That(this ExplicitThisByConv) { + return {}; + } + + void operator()(this That, long long) {} + }; + + ExplicitThisByConv explicit_this_by_conv_functor{}; + + F f20(explicit_this_by_conv_functor); + F f21(as_const(explicit_this_by_conv_functor)); + F f22(move(explicit_this_by_conv_functor)); + F f23(move(as_const(explicit_this_by_conv_functor))); + + static_assert(is_same_v>); + static_assert(is_same_v>); + static_assert(is_same_v>); + static_assert(is_same_v>); + + struct ExplicitThisNoexcept { + float operator()(this ExplicitThisNoexcept, double) noexcept { + return 3.14f; + } + }; + + ExplicitThisNoexcept explicit_this_noexcept_functor{}; + + F f24(explicit_this_noexcept_functor); + F f25(as_const(explicit_this_noexcept_functor)); + F f26(move(explicit_this_noexcept_functor)); + F f27(move(as_const(explicit_this_noexcept_functor))); + + static_assert(is_same_v>); + static_assert(is_same_v>); + static_assert(is_same_v>); + static_assert(is_same_v>); +#endif // HAS_EXPLICIT_THIS_PARAMETER } void test_searchers() {