• enable_if


    一、enable_if 的定义

    enable_if 是c++11标准引入的一个类模板,它的使用体现了c++编译器的SFINAE特性。对于没有使用过enable_if的同学来说,可能会显得有点突兀,下面先来一个例子。

    template<typename T>
    struct MEB
    {
    using type = T;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    接着在main中如下使用:

    MEB<int>::type abc = 15;
    
    • 1

    不难看到MEB::type 代表的就是int 类型。在理解了上面的例子后,接下来看看enable_if的实现源码,源码非常简单,如下:

    template<bool _Test,class _Ty = void>
    struct enable_if {};
    
    template<class _Ty>
    struct enable_if<true,_Ty>
    {
    using type = _Ty;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    上述代码中定义了一个enbale_if类模板,其中_Test为非类型模板参数,_Ty为类型模板参数;接着实现了一个enable_if的偏特化版本,第一个参数设置为true.其实这个偏特化可以理解为一种条件分支语句,如enable_if类模板,当其第一个模板参数为true的时候,对应的分支就是偏特化版本的分支,反之就是泛化版本的分支。

    二、enable_if的使用

    在mian中添加如下代码:

    std::enable_if< (3>2) >::type *myptr = nullptr;
    
    • 1

    编译一下,没有语法错误。因为该表达式的结果为true,走了偏特化的版本,第二个模板参数没有在程序中提供,就走了模板参数的默认值,void类型,所以上面的代码等价于:

    void *myptr = nullptr;
    
    • 1

    但是如果改为如下的代码:

    std::enable_if< (3<2) >::type *myptr = nullptr;
    
    • 1

    编译就如下提示:
    在这里插入图片描述
    这是由于走了泛化版本,这个版本中根本没有type这个类型别名。

    ebable_if用于函数模板中:
    有如下例子:

    template<typename T>
    typename std::enable_if<(sizeof(T) > 2) >::type funceb()
    {
    //...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    现在在main中如下调用:

    funceb<int>();
    
    • 1

    编译后发现没有错误,因为sizeof(int)>2.也就是将这个函数模板被实例化为:

    void  funceb()
    {
    //...
    }
    
    • 1
    • 2
    • 3
    • 4

    那如果如下调用,便会出错

    funceb<char> ();
    
    • 1

    这是由于sizeof(char)<2,不满足条件,也没有找到其他合适的函数,所以会报错。
    c++14标准对enable_if的用法做了简化,只需要在其后面增加一个_t,就可以省略typename和::type的输入,如下修改:

    template<typename T>
    typename std::enable_if_t<(sizeof(T) > 2) > funceb()
    {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    现在试想,如果给函数模板funceb()中的enable_if_t提供第二个模板参数,也就是

    template<typename T>
    std::enable_if_t<(sizeof(T) > 2), T > funceb()
    {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    那么当遇到funceb();会被实例化为:

    int funceb()
    {
    //...
    }
    
    • 1
    • 2
    • 3
    • 4

    这显然需要一个返回值嘛,
    在这里插入图片描述
    于是修改为:

    template<typename T>
    std::enable_if_t<(sizeof(T) > 2), T > funceb()
    {
    	T t = {};
    	return t;
    }
    
    int main()
    {	
    	int c = funceb<int>();
    	cout << c << endl;
    	
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    结果:
    在这里插入图片描述

  • 相关阅读:
    Go语言实用用法大全
    计算机毕业设计-招聘报名系统SpringBoot+JSP【代码讲解+安装调试+文档指导】
    opencv图像卷积操作和常用的图像滤波函数
    面向金融行业的灾备云平台建设项目实践
    GO语言篇之unsafe
    研发主管接私活被辞退,法院判决公司赔偿20.7万元
    PMP每日一练 | 考试不迷路-11.11(包含敏捷+多选)
    【视频】结构方程模型SEM分析心理学营销数据路径图可视化|数据分享
    Redis 内存淘汰和过期删除策略
    用async函数和await解决回调函数地狱
  • 原文地址:https://blog.csdn.net/FairLikeSnow/article/details/125470341