зеркало из https://github.com/microsoft/STL.git
<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:
Родитель
4e97255b35
Коммит
0381c25b10
|
@ -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)>);
|
||||
|
|
Загрузка…
Ссылка в новой задаче