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;
    }
    
  • 相关阅读:
    Android 拍照 代码实例
    利用Android手机里的摄像头进行拍照
    看视频时,类加载器没太理解,现在再整理下几个要点
    关于java设计模式与极品飞车游戏的思考
    【Mood-3】心声
    源自梦想 eclipse快捷键整理
    2020重新出发,JAVA语言,JAVA的诞生和发展史
    2020重新出发,序章: 语言的诞生
    2020重新出发,JAVA学前了解,DOS常用命令
    2020重新出发,JAVA学前了解,Windosws常用快捷键
  • 原文地址:https://www.cnblogs.com/gnivor/p/15546247.html
Copyright © 2011-2022 走看看