C++20概念

1 概述

C++20引入了一个重要的特性-概念。也引入了两个关键字 conceptrequires,分别对应概念和约束。

优点

  1. concept提供了一种在模板编程中,对类型进行约束和限制的方法,简洁明确。
  2. requires提供了一种简单的约束编写方式。
    下面,先讲约束,再将概念。

2 约束

约束以两种形式表现,分别为约束表达式和约束子句。

1 requires约束子句

语法requires cond1 && cond2 && ...
以 requires 开头,后面跟上约束子句。约束子句是一个条件表达式,由一系列约束条件组成,可以使用 &&||
比如

requires true && sizeof(int) == 4 && std::same_as<int, int>;

2 约束表达式

语法:requires(...) {...}

以requires开头,圆括号里面是参数列表,可以声明在表达式中使用的变量,大括号里面是一系列约束要求。

分类

大括号内的约束要求主要分为三种:

  1. 普通的约束要求,要求可执行。
  2. 约束子句
  3. {} -> 这样的特殊约束方式

下面分别举例说明。

比如

  • 普通约束
template <typename T>
concept cpt = requires(T t, int a) {
	//不要多想,typename只不过是告诉编译器value_type是一个类型名而不是一个变量名。
	typename T::value_type; //约束T类中有一个value_type类型别名	
	T::value;//约束T类中有一个value静态变量或常量
	t.print();//约束T类的实例应该可以调用这个方法
};
  • 约束子句
template <typename T>
concept cpt = requires (T t) {
	requires sizeof(T) == 4 && std::same_as<T, int> || true;
	//这里应该能看处理,约束子句和约表达式可以来回嵌套使用
	requires requires(int) {
		requires sizeof(int) == 4;
	};
	requires sizeof(int);//error:不是bool
	requires T::val; //如果val不是bool类型,也是错误的
	requires static_cast<bool>(T::val);//对的
};

  • 特殊约束

首先说明一下,每个部分的作用。
{}推导类型,可以推导变量的类型,也可以推导函数调用返回值类型。
->用来传递使用{}推导的类型给"概念"。(应该是只能传递{}推导的类型)

接下来,再来说明一下推导的规则。

  1. 左值 -> 类型引用
  2. 纯右值 -> 普通类型
  3. 将亡值 -> 右值引用
  4. 函数调用 ->函数返回值类型
  5. 修饰符在推导时不会丢弃
template <typename T>
concept test1 = requires (T t, T&& t_) {
    {t} -> std::same_as<T&>; //T类型的左值
    {T{}} -> std::same_as<T>; //一个匿名右值
    {t_} -> std::same_as<T&>; //T&&类型的左值
    {std::move(t)} -> std::same_as<T&&>; //一个将亡值
     {t.print()} noexcept; //不会抛出异常
    { std::declval<int>()} noexcept -> std::same_as<int&&>; // 该函数不会抛出异常,并且返回值类型为int&&
};

总结

  1. 约束子句和约束表达式可以任意嵌套使用
  2. 可以使用约束子句的地方,不可以使用约束表达式,反之,同理
  3. 约束表达式是一个常量bool表达式, 约束子句每一个约束条件也必须是bool类型
  4. 约束表达式可以在任何地方使用,比如 if语句,但requires约束子句在约束表达式中或模板声明中使用。

3 概念

1 概念的定义

下面是一个最简单的概念模板

template <typename T>
concept cpt = true;

引出定义概念的语法:

模板变量的声明
concept cpt = 约束子句;

其中,约束子句的使用和上面讲的相同。

举例

定义了一个概念,约束模板参数要是一个无符号的整数类型。

template <typename T>
concept cpt = std::is_integral_v<T> && std::is_unsigned<T>::value;

2 使用

1 模板声明处

  • 替代typename 声明一个模板参数
template <cpt T>
void fun ();
  • 约束auto推导的类型
cpt auto a = 1;

2 作为常量布尔表达式使用

	if constexpr (cpt<int>) {}
    if constexpr (requires(int a) {typename type::value_type;}) {}

看得再多不如自己写一遍。我也是看他人的,自己多尝试,又重新做了总结。
如果有什么错误,可以指出。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值