在libcxx/include/type_traits
中,std::is_function
的实现非常紧凑:
namespace __libcpp_is_function_imp
{
struct __dummy_type {};
template <class _Tp> char __test(_Tp*);
template <class _Tp> char __test(__dummy_type);
template <class _Tp> __two __test(...);
template <class _Tp> _Tp& __source(int);
template <class _Tp> __dummy_type __source(...);
}
template <class _Tp, bool = is_class<_Tp>::value ||
is_union<_Tp>::value ||
is_void<_Tp>::value ||
is_reference<_Tp>::value ||
__is_nullptr_t<_Tp>::value >
struct __libcpp_is_function
: public integral_constant<bool,
sizeof(__libcpp_is_function_imp::__test<_Tp>(
__libcpp_is_function_imp::__source<_Tp>(0))) == 1>
{};
template <class _Tp> struct __libcpp_is_function<_Tp, true> : public false_type {};
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_function
: public __libcpp_is_function<_Tp> {};
我有大致的想法。 如果类型与任何非函数类型(类,联合,无效,引用,nullptr_t)都不匹配,则为函数类型。。但是,我找不到此行的含义:
sizeof(__libcpp_is_function_imp::__test<_Tp>(__libcpp_is_function_imp::__source<_Tp>(0))) == 1
我认为__libcpp_is_function_imp::__source<_Tp>(0)
的结果类型应该为_Tp&
。因此,__libcpp_is_function_imp::__test<_Tp>(_Tp&)
的结果类型应为_two
。并且sizeof(_two)
应该等于2,这与1
不同。换句话说,方程sizeof(__libcpp_is_function_imp::__test<_Tp>(__libcpp_is_function_imp::__source<_Tp>(0))) == 1
始终为假。
但是我必须弄错了。有人可以指出我吗?
答案 0 :(得分:4)
C ++中的每种类型都完全属于以下类别之一,可能符合cv要求:
void
decltype(nullptr)
(又称std::nullptr_t
)T*
用于某些类型T
)class
或struct
union
在消除了class
,union
,void
,引用和std::nullptr_t
之后,我们剩下了以下可能的类型:
剩余的模板元编程利用了关于这些剩余类别中的类型的两个事实:
_Tp
是abominable function type,则创建引用类型_Tp&
的尝试格式错误。否则,_Tp&
格式正确。_Tp
是函数类型时,类型_Tp*
才能通过函数到指针的转换转换为_Tp
。留给读者的练习是确定为什么在更早的阶段之前必须消除class
,union
,void
,引用和std::nullptr_t
类型该测试将正常工作。