背景:
c++标准库里边很多地方都用到了decay,网上也有很多资料也介绍了decay,大多都是讲怎么用,没有从源码分析,类型退化的用法以及源码分析
std::decay demo
C++ #include <type_traits> template <typename T, typename U> struct decay_equiv : std::is_same<typename std::decay<T>::type, U>::type {}; template <typename T, typename U> constexpr bool is_decay_equ = decay_equiv<T, U>::value; int main() { static_assert( is_decay_equ<int, int> && ! is_decay_equ<int, float> && is_decay_equ<int&, int> && is_decay_equ<int&&, int> && is_decay_equ<const int&, int> && is_decay_equ<int[2], int*> && ! is_decay_equ<int[4][2], int*> && ! is_decay_equ<int[4][2], int**> && is_decay_equ<int[4][2], int(*)[2]> && is_decay_equ<int(int), int(*)(int)> ); } |
这里可以看的出来,经过decay过后int[4][2] 退化成 int(*)[2],int(int) 退化成int(*)(int),感觉挺神奇的,就从源码角度来看它是怎么做到的
std::decay 源码
C++ template <class _Tp> struct _LIBCPP_TEMPLATE_VIS decay { private: typedef _LIBCPP_NODEBUG_TYPE typename remove_reference<_Tp>::type _Up; public: typedef _LIBCPP_NODEBUG_TYPE typename __decay<_Up, __is_referenceable<_Up>::value>::type type; }; |
可以看的出来,以上来就去除了_Tp 的引用, __is_referenceable<_Up>::value判定是否可引用
__is_referenceable
C++ struct __is_referenceable_impl { template <class _Tp> static _Tp& __test(int); template <class _Tp> static __two __test(...); };
template <class _Tp> struct __is_referenceable : integral_constant<bool, _IsNotSame<decltype(__is_referenceable_impl::__test<_Tp>(0)), __two>::value> {}; |
__is_referenceable_impl 这里会用SFINAE 的原则,如果是可以引用会推到成_Tp&, 否则会推到成__two,这也就是下边_IsNotSame会判定它类型是否一致,也就是说多为数组,以及函数,__is_referenceable<_Up>::value>::type 推到出的是false
接下来看下__decay 的定义
__decay
C++ template <class _Up, bool> struct __decay { typedef _LIBCPP_NODEBUG_TYPE typename remove_cv<_Up>::type type; };
template <class _Up> struct __decay<_Up, true> { public: typedef _LIBCPP_NODEBUG_TYPE typename conditional < is_array<_Up>::value, typename remove_extent<_Up>::type*, typename conditional < is_function<_Up>::value, typename add_pointer<_Up>::type, typename remove_cv<_Up>::type >::type >::type type; }; |
上边可以看出来有2个版本,上边是泛化版本针对普通类型,会先调用remove_cv这个,去除类型的const与volatile
最主要看下边的特化版本的意思,这里需要一部分一部分分析,首先看下
C++ typename conditional < is_array<_Up>::value, typename remove_extent<_Up>::type*,...> |
它先通过conditional 条件判断, is_array<_Up>::value,_Up 是不是数组,如果是数组,他会typename remove_extent<_Up>::type 它会移除一个扩展[],用*号替代,如果不是数组呢
接着看
C++ typename conditional < is_function<_Up>::value, typename add_pointer<_Up>::type, typename remove_cv<_Up>::type >::type |
它会判断是否是函数,如果是函数,就add_pointer<_Up>, 转换成指针,否则移除remove_cv
通过上边可以看的出来,数组与函数具体是怎么退出成指针的。设计挺有意思的
原文地址:https://www.jb51.cc/wenti/3286090.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。