Skip to content
Merged
30 changes: 23 additions & 7 deletions stl/inc/type_traits
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ struct is_void : bool_constant<is_void_v<_Ty>> {};
template <class... _Types>
using void_t = void;

template <class _Ty>
struct _Identity {
using type = _Ty;
};
template <class _Ty>
using _Identity_t _MSVC_KNOWN_SEMANTICS = typename _Identity<_Ty>::type;

// Type modifiers
template <class _Ty>
struct add_const { // add top-level const qualifier
Expand Down Expand Up @@ -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 <class _Ret, class _Self, class... _Args> \
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 <class _Ty>
_INLINE_VAR constexpr bool is_member_function_pointer_v = __is_member_function_pointer(_Ty);
Expand Down Expand Up @@ -1382,13 +1405,6 @@ template <class _Ty1, class _Ty2, class _Ty3, class... _Rest>
struct common_reference<_Ty1, _Ty2, _Ty3, _Rest...> : _Fold_common_reference<void, _Ty1, _Ty2, _Ty3, _Rest...> {};
#endif // _HAS_CXX20

template <class _Ty>
struct _Identity {
using type = _Ty;
};
template <class _Ty>
using _Identity_t _MSVC_KNOWN_SEMANTICS = typename _Identity<_Ty>::type;

#if _HAS_CXX20
template <class _Ty>
struct type_identity {
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/Dev11_0535636_functional_overhaul/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ STATIC_ASSERT(is_member_object_pointer_v<int X::*>);
STATIC_ASSERT(!is_member_function_pointer_v<int X::*>);
STATIC_ASSERT(!is_member_object_pointer_v<int (X::*)(int, int)>);

// 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<int (*)(X, int)>);


// N4594 20.13.7.6 [meta.trans.other]:
// Template:
Expand Down
88 changes: 88 additions & 0 deletions tests/std/tests/P0433R2_deduction_guides/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
#include <shared_mutex>
#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 <typename T>
Expand Down Expand Up @@ -328,6 +332,90 @@ void test_function_wrapper() {

static_assert(is_same_v<decltype(f9), F<double(const double&, const double&)>>);
static_assert(is_same_v<decltype(f10), F<int(int, int)>>);

#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<decltype(f11), F<void(char)>>);
static_assert(is_same_v<decltype(f12), F<void(char)>>);
static_assert(is_same_v<decltype(f13), F<void(char)>>);
static_assert(is_same_v<decltype(f14), F<void(char)>>);

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<decltype(f15), F<void(short)>>);

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<decltype(f16), F<void(int)>>);
static_assert(is_same_v<decltype(f17), F<void(int)>>);
static_assert(is_same_v<decltype(f18), F<void(int)>>);
static_assert(is_same_v<decltype(f19), F<void(int)>>);

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<decltype(f20), F<void(long long)>>);
static_assert(is_same_v<decltype(f21), F<void(long long)>>);
static_assert(is_same_v<decltype(f22), F<void(long long)>>);
static_assert(is_same_v<decltype(f23), F<void(long long)>>);

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<decltype(f24), F<float(double)>>);
static_assert(is_same_v<decltype(f25), F<float(double)>>);
static_assert(is_same_v<decltype(f26), F<float(double)>>);
static_assert(is_same_v<decltype(f27), F<float(double)>>);
#endif // HAS_EXPLICIT_THIS_PARAMETER
}

void test_searchers() {
Expand Down