【C++】概念与约束

  • ~1.93K 字
  1. 1. 概念与约束
    1. 1.1. requires
      1. 1.1.1. requires表达式
      2. 1.1.2. 嵌套要求
      3. 1.1.3. requires子句
    2. 1.2. concept

概念与约束

C++20引入了概念和约束的概念,用于限定模板类型实参的范围

新增了两个关键字concept与requires用于实现要求

requires

requires表达式

1
2
3
4
5
6
requires(Type1 para1, Type2 para2, ...){
要求1;
要求2;
...
要求n;
}

require可以有0-n个参数,大括号内有0-n个表达式

require表达式是常量表达式,编译时求值,依次对要求进行判断,遇到第一个无效表达式时返回false,若所有表达式都是有效或良构的,返回true

注意:每条要求不会被实例化或求值,仅用于判断有效

例1:

1
2
3
4
5
6
7
8
9
10
11
12
template <typename T>
bool isAddable(T a, T b){
bool result =
requires(T a, T b){
a+b;
a++;
a+=b;
++a;
{a*1}->std::convertible_to<T>;
};
return result;
}

其中最后一条为复合要求:

大括号里用于判断是否是有效的表达式,右箭头后面判断表达式的值是否符合某些条件

当T为int时,要求都可以成立,表达式的值为true

当T为string时,a++是无效的,表达式的值为false

例2:

1
2
3
4
5
6
7
8
template<typename T>
constexpr bool isIteratable(){
bool result =
requires{
typename T::iterator;
};
return result;
}

这个例子中,还有一种要求为条件要求:

格式为typename 表达式,判断类型是否有效

当T为int时,int内没有迭代器,表达式的值为false

当T为string时,string内嵌了迭代器,表达式的值为true

嵌套要求

语法:require 约束表达式

1
2
3
4
5
6
7
8
template<typename T>
constexpr bool isFloat(){
bool result =
requires{
requires std::is_floating_point_v<T>;
};
return result;
}

此处约束表达式用于判断是否是浮点数

requires子句

语法:requires 常量表达式(约束)

1
2
3
4
5
template<typename T>
requires std::is_integral<T>::value
bool is_even(T i){
return i%2==0;
}

该函数模板设定了一个requires子句,判断传参是否为整型,只有满足该子句函数模板才能实例化,否则编译会报错

requires子句中的表达式也可以使用requires表达式

requires子句中也可以使用&&与||,前者需要满足所有约束,后者需要至少满足一项约束

concept

以上例子中的约束条件即为匿名概念,我们可以将约束条件定义为一个概念

1
2
template<模板参数列表>
concept ConcentName = 约束表达式;

定义后我们可以直接使用概念

1
2
3
4
5
template<typename T>
requires std::integral<T>
bool is_odd(T i){
return i%2!=0;
}

这里requires子句中使用了预定义的概念integral,定义如下:

1
2
template<typename _Tp>
concept integral = is_integral_v<_Tp>;

或将模板中typename替换为概念

或使用概念+auto来定义形参

1
2
3
bool is_odd(std::integral auto i){
return i%2!=0;
}

通常定义概念时,概念应该有明确语义

<concept>头文件中也提供了许多预定义概念,大部分类型特征都有对应概念定义

赞助喵
非常感谢您的喜欢!
赞助喵