<type_traits>: is_function simplification (#460)

Fixes #198.

Co-authored-by: Casey Carter <cacarter@microsoft.com>
Co-authored-by: Stephan T. Lavavej <stl@microsoft.com>
This commit is contained in:
ArtemSarmini 2020-08-02 01:29:40 +03:00 коммит произвёл GitHub
Родитель 4e97255b35
Коммит 0381c25b10
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 150 добавлений и 135 удалений

Просмотреть файл

@ -638,7 +638,7 @@ _NODISCARD const_mem_fun1_ref_t<_Result, _Ty, _Arg> mem_fun_ref(_Result (_Ty::*_
// FUNCTION TEMPLATE mem_fn
template <class _Memptr>
class _Mem_fn : public _Weak_types<_Memptr>::type {
class _Mem_fn : public _Weak_types<_Memptr> {
private:
_Memptr _Pm;
@ -1449,7 +1449,7 @@ template <class _Ret, class _Fx>
struct _Binder_result_type { // provide result_type (sometimes)
using _Decayed = decay_t<_Fx>;
using _All_weak_types = typename _Weak_types<_Decayed>::type;
using _All_weak_types = _Weak_types<_Decayed>;
using type =
conditional_t<is_same_v<_Ret, _Unforced>, _Weak_result_type<_All_weak_types>, _Forced_result_type<_Ret>>;

Просмотреть файл

@ -72,84 +72,6 @@ struct negation : bool_constant<!static_cast<bool>(_Trait::value)> {}; // The ne
template <class _Trait>
_INLINE_VAR constexpr bool negation_v = negation<_Trait>::value;
// STRUCT TEMPLATE _Arg_types
template <class... _Types>
struct _Arg_types {}; // provide argument_type, etc. (sometimes)
template <class _Ty1>
struct _Arg_types<_Ty1> {
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty1 _ARGUMENT_TYPE_NAME;
};
template <class _Ty1, class _Ty2>
struct _Arg_types<_Ty1, _Ty2> {
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty1 _FIRST_ARGUMENT_TYPE_NAME;
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty2 _SECOND_ARGUMENT_TYPE_NAME;
};
// STRUCT TEMPLATE is_function
template <class _Ty>
struct _Is_function { // determine whether _Ty is a function
using _Bool_type = false_type; // NB: members are user-visible via _Weak_types
};
#define _IS_FUNCTION(CALL_OPT, CV_OPT, REF_OPT, NOEXCEPT_OPT) \
template <class _Ret, class... _Types> \
struct _Is_function<_Ret CALL_OPT(_Types...) CV_OPT REF_OPT NOEXCEPT_OPT> : _Arg_types<_Types...> { \
using _Bool_type = true_type; \
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ret _RESULT_TYPE_NAME; \
};
_NON_MEMBER_CALL_CV_REF_NOEXCEPT(_IS_FUNCTION)
#undef _IS_FUNCTION
#define _IS_FUNCTION_ELLIPSIS(CV_REF_NOEXCEPT_OPT) \
template <class _Ret, class... _Types> \
struct _Is_function<_Ret(_Types..., ...) CV_REF_NOEXCEPT_OPT> { /* no calling conventions for ellipsis */ \
using _Bool_type = true_type; \
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ret _RESULT_TYPE_NAME; \
};
_CLASS_DEFINE_CV_REF_NOEXCEPT(_IS_FUNCTION_ELLIPSIS)
#undef _IS_FUNCTION_ELLIPSIS
template <class _Ty>
struct is_function : _Is_function<_Ty>::_Bool_type {}; // determine whether _Ty is a function
template <class _Ty>
_INLINE_VAR constexpr bool is_function_v = _Is_function<_Ty>::_Bool_type::value;
template <class _Ty>
struct _Is_memfunptr { // base class for member function pointer predicates
using _Bool_type = false_type; // NB: members are user-visible via _Weak_types
};
#define _IS_MEMFUNPTR(CALL_OPT, CV_OPT, REF_OPT, NOEXCEPT_OPT) \
template <class _Ret, class _Arg0, class... _Types> \
struct _Is_memfunptr<_Ret (CALL_OPT _Arg0::*)(_Types...) CV_OPT REF_OPT NOEXCEPT_OPT> \
: _Arg_types<CV_OPT _Arg0*, _Types...> { \
using _Bool_type = true_type; \
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ret _RESULT_TYPE_NAME; \
using _Class_type = _Arg0; \
using _Guide_type = enable_if<!is_same_v<int REF_OPT, int&&>, _Ret(_Types...)>; \
};
_MEMBER_CALL_CV_REF_NOEXCEPT(_IS_MEMFUNPTR)
#undef _IS_MEMFUNPTR
#define _IS_MEMFUNPTR_ELLIPSIS(CV_REF_NOEXCEPT_OPT) \
template <class _Ret, class _Arg0, class... _Types> \
struct _Is_memfunptr<_Ret (_Arg0::*)(_Types..., ...) \
CV_REF_NOEXCEPT_OPT> { /* no calling conventions for ellipsis */ \
using _Bool_type = true_type; \
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ret _RESULT_TYPE_NAME; \
using _Class_type = _Arg0; \
using _Guide_type = enable_if<false>; \
};
_CLASS_DEFINE_CV_REF_NOEXCEPT(_IS_MEMFUNPTR_ELLIPSIS)
#undef _IS_MEMFUNPTR_ELLIPSIS
// STRUCT TEMPLATE is_void
template <class _Ty>
_INLINE_VAR constexpr bool is_void_v = is_same_v<remove_cv_t<_Ty>, void>;
@ -379,33 +301,6 @@ _INLINE_VAR constexpr bool is_reference_v<_Ty&&> = true;
template <class _Ty>
struct is_reference : bool_constant<is_reference_v<_Ty>> {};
// STRUCT TEMPLATE is_member_object_pointer
template <class _Ty, bool _Pmf = _Is_memfunptr<_Ty>::_Bool_type::value>
struct _Is_member_object_pointer { // determine whether _Ty is a pointer to member object
static constexpr bool value = false;
};
template <class _Ty1, class _Ty2>
struct _Is_member_object_pointer<_Ty1 _Ty2::*, false> {
static constexpr bool value = true;
using _Class_type = _Ty2;
};
template <class _Ty>
_INLINE_VAR constexpr bool is_member_object_pointer_v = // determine whether _Ty is a pointer to member object
_Is_member_object_pointer<remove_cv_t<_Ty>>::value;
template <class _Ty>
struct is_member_object_pointer : bool_constant<is_member_object_pointer_v<_Ty>> {};
// STRUCT TEMPLATE is_member_function_pointer
template <class _Ty>
_INLINE_VAR constexpr bool is_member_function_pointer_v = // determine whether _Ty is a pointer to member function
_Is_memfunptr<remove_cv_t<_Ty>>::_Bool_type::value;
template <class _Ty>
struct is_member_function_pointer : bool_constant<is_member_function_pointer_v<_Ty>> {};
// STRUCT TEMPLATE is_pointer
template <class>
_INLINE_VAR constexpr bool is_pointer_v = false; // determine whether _Ty is a pointer
@ -454,13 +349,6 @@ _INLINE_VAR constexpr bool is_fundamental_v = is_arithmetic_v<_Ty> || is_void_v<
template <class _Ty>
struct is_fundamental : bool_constant<is_fundamental_v<_Ty>> {}; // determine whether _Ty is a fundamental type
// STRUCT TEMPLATE is_object
template <class _Ty>
_INLINE_VAR constexpr bool is_object_v = !is_function_v<_Ty> && !is_reference_v<_Ty> && !is_void_v<_Ty>;
template <class _Ty>
struct is_object : bool_constant<is_object_v<_Ty>> {}; // determine whether _Ty is an object type
// STRUCT TEMPLATE is_convertible
template <class _From, class _To>
struct is_convertible : bool_constant<__is_convertible_to(_From, _To)> {
@ -484,20 +372,63 @@ struct is_compound : bool_constant<!is_fundamental_v<_Ty>> {}; // determine whet
template <class _Ty>
_INLINE_VAR constexpr bool is_compound_v = !is_fundamental_v<_Ty>;
// STRUCT TEMPLATE is_member_pointer
// STRUCT TEMPLATE _Arg_types
template <class... _Types>
struct _Arg_types {}; // provide argument_type, etc. when sizeof...(_Types) is 1 or 2
template <class _Ty1>
struct _Arg_types<_Ty1> {
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty1 _ARGUMENT_TYPE_NAME;
};
template <class _Ty1, class _Ty2>
struct _Arg_types<_Ty1, _Ty2> {
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty1 _FIRST_ARGUMENT_TYPE_NAME;
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty2 _SECOND_ARGUMENT_TYPE_NAME;
};
// STRUCT TEMPLATE is_member_function_pointer
template <class _Ty>
_INLINE_VAR constexpr bool is_member_pointer_v = is_member_object_pointer_v<_Ty> || is_member_function_pointer_v<_Ty>;
struct _Is_memfunptr { // base class for member function pointer predicates
using _Bool_type = false_type; // NB: members are user-visible via _Weak_types
};
#define _IS_MEMFUNPTR(CALL_OPT, CV_OPT, REF_OPT, NOEXCEPT_OPT) \
template <class _Ret, class _Arg0, class... _Types> \
struct _Is_memfunptr<_Ret (CALL_OPT _Arg0::*)(_Types...) CV_OPT REF_OPT NOEXCEPT_OPT> \
: _Arg_types<CV_OPT _Arg0*, _Types...> { \
using _Bool_type = true_type; \
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ret _RESULT_TYPE_NAME; \
using _Class_type = _Arg0; \
using _Guide_type = enable_if<!is_same_v<int REF_OPT, int&&>, _Ret(_Types...)>; \
};
_MEMBER_CALL_CV_REF_NOEXCEPT(_IS_MEMFUNPTR)
#undef _IS_MEMFUNPTR
#define _IS_MEMFUNPTR_ELLIPSIS(CV_REF_NOEXCEPT_OPT) \
template <class _Ret, class _Arg0, class... _Types> \
struct _Is_memfunptr<_Ret (_Arg0::*)(_Types..., ...) \
CV_REF_NOEXCEPT_OPT> { /* no calling conventions for ellipsis */ \
using _Bool_type = true_type; \
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ret _RESULT_TYPE_NAME; \
using _Class_type = _Arg0; \
using _Guide_type = enable_if<false>; \
};
_CLASS_DEFINE_CV_REF_NOEXCEPT(_IS_MEMFUNPTR_ELLIPSIS)
#undef _IS_MEMFUNPTR_ELLIPSIS
#ifdef __clang__
template <class _Ty>
_INLINE_VAR constexpr bool is_member_function_pointer_v = __is_member_function_pointer(_Ty);
#else // ^^^ Clang ^^^ / vvv Other vvv
template <class _Ty>
_INLINE_VAR constexpr bool is_member_function_pointer_v = _Is_memfunptr<remove_cv_t<_Ty>>::_Bool_type::value;
#endif // ^^^ Other ^^^
template <class _Ty>
struct is_member_pointer : bool_constant<is_member_pointer_v<_Ty>> {}; // determine whether _Ty is a pointer to member
// STRUCT TEMPLATE is_scalar
template <class _Ty>
_INLINE_VAR constexpr bool is_scalar_v = // determine whether _Ty is a scalar type
is_arithmetic_v<_Ty> || is_enum_v<_Ty> || is_pointer_v<_Ty> || is_member_pointer_v<_Ty> || is_null_pointer_v<_Ty>;
template <class _Ty>
struct is_scalar : bool_constant<is_scalar_v<_Ty>> {};
struct is_member_function_pointer : bool_constant<is_member_function_pointer_v<_Ty>> {};
// STRUCT TEMPLATE is_const
template <class>
@ -519,6 +450,65 @@ _INLINE_VAR constexpr bool is_volatile_v<volatile _Ty> = true;
template <class _Ty>
struct is_volatile : bool_constant<is_volatile_v<_Ty>> {};
// STRUCT TEMPLATE is_function
template <class _Ty>
_INLINE_VAR constexpr bool is_function_v = // only function types and reference types can't be const qualified
!is_const_v<const _Ty> && !is_reference_v<_Ty>;
template <class _Ty>
struct is_function : bool_constant<is_function_v<_Ty>> {};
// STRUCT TEMPLATE is_object
template <class _Ty>
_INLINE_VAR constexpr bool is_object_v = // only function types and reference types can't be const qualified
is_const_v<const _Ty> && !is_void_v<_Ty>;
template <class _Ty>
struct is_object : bool_constant<is_object_v<_Ty>> {};
// STRUCT TEMPLATE is_member_object_pointer
template <class>
struct _Is_member_object_pointer {
static constexpr bool value = false;
};
template <class _Ty1, class _Ty2>
struct _Is_member_object_pointer<_Ty1 _Ty2::*> {
static constexpr bool value = !is_function_v<_Ty1>;
using _Class_type = _Ty2;
};
#ifdef __clang__
template <class _Ty>
_INLINE_VAR constexpr bool is_member_object_pointer_v = __is_member_object_pointer(_Ty);
#else // ^^^ Clang / Other vvv
template <class _Ty>
_INLINE_VAR constexpr bool is_member_object_pointer_v = _Is_member_object_pointer<remove_cv_t<_Ty>>::value;
#endif // ^^^ Other ^^^
template <class _Ty>
struct is_member_object_pointer : bool_constant<is_member_object_pointer_v<_Ty>> {};
// STRUCT TEMPLATE is_member_pointer
#ifdef __clang__
template <class _Ty>
_INLINE_VAR constexpr bool is_member_pointer_v = __is_member_pointer(_Ty);
#else // ^^^ Clang / Other vvv
template <class _Ty>
_INLINE_VAR constexpr bool is_member_pointer_v = is_member_object_pointer_v<_Ty> || is_member_function_pointer_v<_Ty>;
#endif // ^^^ Other ^^^
template <class _Ty>
struct is_member_pointer : bool_constant<is_member_pointer_v<_Ty>> {}; // determine whether _Ty is a pointer to member
// STRUCT TEMPLATE is_scalar
template <class _Ty>
_INLINE_VAR constexpr bool is_scalar_v = // determine whether _Ty is a scalar type
is_arithmetic_v<_Ty> || is_enum_v<_Ty> || is_pointer_v<_Ty> || is_member_pointer_v<_Ty> || is_null_pointer_v<_Ty>;
template <class _Ty>
struct is_scalar : bool_constant<is_scalar_v<_Ty>> {};
// STRUCT TEMPLATE is_pod
template <class _Ty>
struct _CXX20_DEPRECATE_IS_POD is_pod : bool_constant<__is_pod(_Ty)> {}; // determine whether _Ty is a POD type
@ -1810,7 +1800,28 @@ inline constexpr bool is_nothrow_invocable_r_v =
_Select_invoke_traits<_Callable, _Args...>::template _Is_nothrow_invocable_r<_Rx>::value;
#endif // _HAS_CXX17
// STRUCT TEMPLATE _Weak_types
// ALIAS TEMPLATE _Weak_types
template <class _Ty>
struct _Function_args {}; // determine whether _Ty is a function
#define _FUNCTION_ARGS(CALL_OPT, CV_OPT, REF_OPT, NOEXCEPT_OPT) \
template <class _Ret, class... _Types> \
struct _Function_args<_Ret CALL_OPT(_Types...) CV_OPT REF_OPT NOEXCEPT_OPT> : _Arg_types<_Types...> { \
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ret _RESULT_TYPE_NAME; \
};
_NON_MEMBER_CALL_CV_REF_NOEXCEPT(_FUNCTION_ARGS)
#undef _FUNCTION_ARGS
#define _FUNCTION_ARGS_ELLIPSIS(CV_REF_NOEXCEPT_OPT) \
template <class _Ret, class... _Types> \
struct _Function_args<_Ret(_Types..., ...) CV_REF_NOEXCEPT_OPT> { /* no calling conventions for ellipsis */ \
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ret _RESULT_TYPE_NAME; \
};
_CLASS_DEFINE_CV_REF_NOEXCEPT(_FUNCTION_ARGS_ELLIPSIS)
#undef _FUNCTION_ARGS_ELLIPSIS
template <class _Ty, class = void>
struct _Weak_result_type {}; // default definition
@ -1826,8 +1837,8 @@ struct _Weak_argument_type : _Weak_result_type<_Ty> {}; // default definition
_STL_DISABLE_DEPRECATED_WARNING
template <class _Ty>
struct _Weak_argument_type<_Ty, void_t<typename _Ty::argument_type>>
: _Weak_result_type<_Ty> { // defined if _Ty::argument_type exists
struct _Weak_argument_type<_Ty, void_t<typename _Ty::argument_type>> : _Weak_result_type<_Ty> {
// defined if _Ty::argument_type exists
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef typename _Ty::argument_type _ARGUMENT_TYPE_NAME;
};
_STL_RESTORE_DEPRECATED_WARNING
@ -1846,12 +1857,8 @@ struct _Weak_binary_args<_Ty, void_t<typename _Ty::first_argument_type,
_STL_RESTORE_DEPRECATED_WARNING
template <class _Ty>
struct _Weak_types { // provide nested types (sometimes)
using _Is_f_or_pf = _Is_function<remove_pointer_t<_Ty>>;
using _Is_pmf = _Is_memfunptr<remove_cv_t<_Ty>>;
using type = conditional_t<is_function_v<remove_pointer_t<_Ty>>, _Is_f_or_pf,
conditional_t<is_member_function_pointer_v<_Ty>, _Is_pmf, _Weak_binary_args<_Ty>>>;
};
using _Weak_types = conditional_t<is_function_v<remove_pointer_t<_Ty>>, _Function_args<remove_pointer_t<_Ty>>,
conditional_t<is_member_function_pointer_v<_Ty>, _Is_memfunptr<remove_cv_t<_Ty>>, _Weak_binary_args<_Ty>>>;
// CLASS TEMPLATE reference_wrapper
template <class _Ty>
@ -1868,7 +1875,7 @@ struct _Refwrap_has_ctor_from<_Ty, _Uty, void_t<decltype(_Refwrap_ctor_fun<_Ty>(
template <class _Ty>
class reference_wrapper
#if !_HAS_CXX20
: public _Weak_types<_Ty>::type
: public _Weak_types<_Ty>
#endif // !_HAS_CXX20
{
public:

Просмотреть файл

@ -168,6 +168,14 @@ STATIC_ASSERT(is_member_function_pointer_v<decltype(&Cat::e)>);
STATIC_ASSERT(is_member_function_pointer_v<decltype(&Cat::f)>);
STATIC_ASSERT(is_member_function_pointer_v<decltype(&Cat::g)>);
STATIC_ASSERT(is_member_pointer_v<decltype(&Cat::a)>);
STATIC_ASSERT(is_member_pointer_v<decltype(&Cat::b)>);
STATIC_ASSERT(is_member_pointer_v<decltype(&Cat::c)>);
STATIC_ASSERT(is_member_pointer_v<decltype(&Cat::d)>);
STATIC_ASSERT(is_member_pointer_v<decltype(&Cat::e)>);
STATIC_ASSERT(is_member_pointer_v<decltype(&Cat::f)>);
STATIC_ASSERT(is_member_pointer_v<decltype(&Cat::g)>);
STATIC_ASSERT(is_function_v<decltype(u)>);
STATIC_ASSERT(is_function_v<decltype(v)>);
STATIC_ASSERT(is_function_v<decltype(w)>);