zoukankan      html  css  js  c++  java
  • C++笔记模板类的类型限定: enable_if、static_assert

    0. 参考资料:

    静态断言static_assert: https://www.cnblogs.com/Braveliu/p/12220769.html
    std::enable_if的几种用法: https://blog.csdn.net/jeffasd/article/details/84667090 | https://yixinglu.gitlab.io/enable_if.html

    1. 静态断言语法:

    static_assert(常量表达式,"提示字符串")
    使用static_assert,可以在编译期发现更多的错误,用编译器来强制保证一些契约,帮助我们改善编译信息的可读性,尤其是用于模板时。

    注意:
    [1]使用范围:static_assert可以用在全局作用域中,命名空间中,类作用域中,函数作用域中,几乎可以不受限制的使用。
    [2]常量表达式:static_assert的断言表达式的结果必须是在编译时期可以计算的表达式,即必须是常量表达式,示例如下:

    //确保模板类的入参类型为integer类
    template <typename T>
    T add_2(T t) {
      static_assert(std::is_integral_v<T>, "Type T should be integer");
      return t+1;
    }
    

    错误用法:

    int positive(const int n) {
        static_assert(n > 0, "value must > 0");
        return 0;
    }
    

    2. std::enable

    官方解释

    Enable type if condition is met
    The type T is enabled as member type enable_if::type if Cond is true.
    Otherwise, enable_if::type is not defined.
    This is useful to hide signatures on compile time when a particular condition is not met, since in this case, the member enable_if::type will not be defined and attempting to compile using it should fail.

    It is defined with a behavior equivalent to:

    template<bool Cond, class T = void> struct enable_if {};
    template<class T> struct enable_if<true, T> { typedef T type; };   // 这里利用了上一行定义的struct
    // 只有当第一个模板参数为 true 时,type 才有定义,否则使用 type 会产生编译错误,并且默认模板参数可以让你不必指定类型。
    

    用法一:类型偏特化

    在使用模板编程时,经常会用到根据模板参数的某些特性进行不同类型的选择,或者在编译时校验模板参数的某些特性。

    用法二:控制函数返回类型

    对于模板函数,有时希望根据不同的模板参数返回不同类型的值,进而给函数模板也赋予类型模板特化的性质。

    template <typename T>
    typename std::enable_if_t<std::is_integral_v<T>, bool>
    is_odd(T t) {
      return bool(t%2);
    }
    

    用法三:校验函数模板参数类型

    有时定义的模板函数,只希望特定的类型可以调用

    template <typename T, typename = typename std::enable_if_t<std::is_integral_v<T>>>
    bool is_even(T t) {
      return t%2 == 0;
    }
    

    3. 例程

    #include <iostream>
    #include <type_traits>
     
    template <typename T>
    //typename std::enable_if<std::is_integral<T>::value, bool>::type  // c++11的写法
    typename std::enable_if_t<std::is_integral_v<T>, bool>
    is_odd(T t) {
      return bool(t%2);
    }
     
    //template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>  // c++11的写法
    template <typename T, typename = typename std::enable_if_t<std::is_integral_v<T>>>
    bool is_even(T t) {
      return !is_odd(t); 
    }
    
    template <typename T, typename = typename std::enable_if_t<std::is_integral_v<T>>>
    bool is_even2(T t) {
      return t%2 == 0;
    }
    
    template <typename T, typename = int>
    T add_1(T t) {
      return t+1;
    }
    
    template <typename T>
    T add_1_v3(T t) {
      static_assert(std::is_integral_v<T>, "Type T should be integer");
      return t+1;
    }
    
    template <typename T>
    T add_1_v4(T t) {
      return t+1;
    }
    
    int main() {
        std::cout << is_even(100) << std::endl;
        // std::cout << is_even(100.1) << std::endl; // 编译时无法通过std::enable_if_t<std::is_integral_v<T>>
        std::cout << is_even2(101) << std::endl;
        std::cout << add_1(101) << std::endl;
        std::cout << add_1(101.1) << std::endl;
        //std::cout << add_1_v3(101.1) << std::endl; // 编译时无法通过static_assert
        std::cout << add_1_v3(101) << std::endl;
        return 0;
    }
    
  • 相关阅读:
    MDX查询语句
    MyEclipse 点击 部署 按钮 无效
    C#创建数字证书并导出为pfx,并使用pfx进行非对称加解密
    SSIS – 变量和表达式
    使用 SSIS Foreach Loop 容器 – Foreach Item Enumerator
    SSIS – For Loop Container
    SSIS 中的文件系统任务 (File System Task)
    TypeError: parse() got an unexpected keyword argument 'transport_encoding' 安装tensor后报错
    np基本函数大全
    使用OpenCV对图像进行缩放
  • 原文地址:https://www.cnblogs.com/gnivor/p/15546247.html
Copyright © 2011-2022 走看看