• std::decay 源码分析


    背景:

     c++标准库里边很多地方都用到了decay,网上也有很多资料也介绍了decay,大多都是讲怎么用,没有从源码分析,类型退化的用法以及源码分析

    std::decay demo

    C++
    #include
     
    template
    struct decay_equiv :
        std::is_same::type, U>::type
    {};
    template
    constexpr bool is_decay_equ = decay_equiv::value;
     
    int main()
    {
        static_assert(
            is_decay_equ &&
            ! is_decay_equ &&
            is_decay_equ &&
            is_decay_equ &&
            is_decay_equ &&
            is_decay_equ &&
            ! is_decay_equ &&
            ! is_decay_equ &&
            is_decay_equ &&
            is_decay_equ
        );
    }

    这里可以看的出来,经过decay过后int[4][2] 退化成  int(*)[2],int(int) 退化成int(*)(int),感觉挺神奇的,就从源码角度来看它是怎么做到的

    std::decay 源码

    C++
    template
    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 static _Tp& __test(int);
        template static __two __test(...);
    };

    template
    struct __is_referenceable : integral_constant     _IsNotSame(0)), __two>::value> {};

    __is_referenceable_impl 这里会用SFINAE 的原则,如果是可以引用会推到成_Tp&, 否则会推到成__two,这也就是下边_IsNotSame会判定它类型是否一致,也就是说多为数组,以及函数,__is_referenceable<_Up>::value>::type 推到出的是false

    接下来看下__decay 的定义

    __decay

    C++
    template
    struct __decay {
        typedef _LIBCPP_NODEBUG_TYPE typename remove_cv<_Up>::type type;
    };

    template
    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

    通过上边可以看的出来,数组与函数具体是怎么退出成指针的。设计挺有意思的

  • 相关阅读:
    Ansible常用模块
    nodejs毕业设计源码中介房屋租赁管理系统
    Vue3+Vite+Koa2的一个前后端分离todolist记事本网站
    Navicat 使用教程
    搜维尔科技:Varjo在混合现实中驾驶船舶
    06 前端之Bootstrap框架
    pipeline + node +jenkins+kubernetes部署yarn前端项目
    All in One:Prometheus 多实例数据统一管理最佳实践
    c++语言核心及进阶
    操作系统(Android&IOS)图像绘图的基本原理
  • 原文地址:https://blog.csdn.net/c553110519/article/details/126498128