第十四章:模版(三)

Concepts

模版存在一些固有的问题:我们并没有办法对模版参数引入相应的限制

  • 参数是否可以正常工作,通常需要阅读代码进行理解
  • 编译报错的友好性较差(vector<int &>)

为了解决这个问题,在C++20引入了Concepts:编译器谓词,他可以基于给定的输入,返回truefalse,他可以与constraintsrequire从句)一起使用来限制模版参数。通常我们将constraints置于表示模版形参的尖括号后面进行限制

template <typename T>
concept IsAvail = std::is_same_v<T,int> || std::is_same_v<float,T>;

template <typename T>
    requires IsAvail<T>
void fun(T input){

}

关于Concept的定义与使用,我们需要注意以下几点

  • 包含一个模版参数的Concept
    1. 使用require从句
    2. 直接替换typename
      template <typename T>
      concept IsAvail = std::is_same_v<T,int> || std::is_same_v<float,T>;
      
      template <IsAvail T>
      void fun(T input){
      
      }
      
  • 包含多个模版参数的Concept
    	template <typename T, typename T2>
    concept IsAvail = std::is_same_v<T,T2> ;
    
    template <typename T1, typename T2>
        requires IsAvail<T1,T2>
    void fun(T1 input1, T2 input2){
    
    }
    
    当用作类型constraint时,可以少传递一个参数,推导出的类型将作为首个参数
    template <typename T, typename T2>
    concept IsAvail = std::is_same_v<T,T2> ;
    
    template <IsAvail<int> T>       // 等价于 IsAvail<T,int>
    void fun(T input){
    
    }
    

之后我们来关注require表达式,它主要分为以下几类

  • 简单表达式:表明可以接收的类型
    template <typename T>
    concept Addable =
    requires (T a, T b){
        a+b;
    };
    
  • 类型表达式:表明是一个有效的类型
    template <typename T>
    concept Avail =
    requires {
        typename T::inter;
    }
    
  • 符合表达式:表明操作的有效性,以及操作返回类型的特性
    template <typename T>
    concept Avail =
    requires (T x)  {
        {x+1} -> int ;
    }
    
  • 嵌套表达式:包含其它的限定表达式

需要注意区分requires从句与requires表达式,具体参考这里

requirea从句会影响重载解析与特化版本的选取

  • 只有 requires 从句有效而且返回为 true 时相应的模板才会被考虑
  • requires 从句所引入的限定具有偏序特性,系统会选择限制最严格的版本
    template <typename T>
    concept C1 = std::is_same_v<T,int>;
    
    
    template <typename T>
    concept C2 = std::is_same_v<T,int> || std::is_same_v<T,float>;
    
    
    template <C1 T>
    void fun(T){
        std::cout << "1\n";
    }
    
    template <C2 T>
    void fun(T){
        std::cout << "2\n";
    }
    
    int main() {
        fun(3);         //输出为1
    }
    

这里有一个特化小技巧:我们在声明中引入“ A||B” 进行限制,之后分别针对 A 与 B 引入特化

template <typename T>
    requires std::is_same_v<T,int> || std::is_same_v<T,double>
class B;

template <>
class B<int>{

};

template <>
class B<double>{

};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值