赞
踩
C++20引入了一个重要的特性-概念。也引入了两个关键字 concept
和 requires
,分别对应概念和约束。
约束以两种形式表现,分别为约束表达式和约束子句。
语法:requires cond1 && cond2 && ...
以 requires 开头,后面跟上约束子句。约束子句是一个条件表达式,由一系列约束条件组成,可以使用 &&
和 ||
。
比如:
requires true && sizeof(int) == 4 && std::same_as<int, int>;
requires(...) {...}
以requires开头,圆括号里面是参数列表,可以声明在表达式中使用的变量,大括号里面是一系列约束要求。
大括号内的约束要求主要分为三种:
下面分别举例说明。
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);//对的
};
首先说明一下,每个部分的作用。
{}
推导类型,可以推导变量的类型,也可以推导函数调用返回值类型。
->
用来传递使用{}
推导的类型给"概念"。(应该是只能传递{}
推导的类型)
接下来,再来说明一下推导的规则。
->
类型引用->
普通类型->
右值引用->
函数返回值类型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&&
};
if语句
,但requires
约束子句在约束表达式中或模板声明中使用。下面是一个最简单的概念模板
template <typename T>
concept cpt = true;
引出定义概念的语法:
模板变量的声明
concept cpt = 约束子句;
其中,约束子句的使用和上面讲的相同。
定义了一个概念,约束模板参数要是一个无符号的整数类型。
template <typename T>
concept cpt = std::is_integral_v<T> && std::is_unsigned<T>::value;
template <cpt T>
void fun ();
cpt auto a = 1;
if constexpr (cpt<int>) {}
if constexpr (requires(int a) {typename type::value_type;}) {}
看得再多不如自己写一遍。我也是看他人的,自己多尝试,又重新做了总结。
如果有什么错误,可以指出。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。