首页 > 编程语言 ># 关于C++20Concept(概念)及requires表达式的学习

# 关于C++20Concept(概念)及requires表达式的学习

时间:2022-08-29 23:34:32浏览次数:82  
标签:std concept integral C++ template requires 模板 20Concept

关于C++20Concept(概念)及requires表达式的学习

Concept(概念)

C++20 引入了 concept 以在编译期检查模板实参是否满足指定的约束.

如何不用concept进行约束

template <typename T>
T inc(T& a) {
    static_assert(std::is_integral<T>::value);
    return ++a;
}

如果使用double a; inc(a);运行时就会报错(和assert差不多)

虽然可以解决问题,但是T的检查是在函数内实现的,调用时出错了,用户才知道。不能从函数inc的声明直观看出T的要求。而concept会直接报错

//c++ concepts库内对整型的类型限制

template <typename T>
concept integral = std::is_integral<T>::value;

写法

以下展示四种写法(关于requires表达式,稍后再讲)

template <integral T>
T inc(T& a) { return ++a; }
integral auto inc(integral auto a) { return ++a; }
template <typename T>
T inc(T a) requires integral<T> { return ++a; }
template <typename T>
requires integral<T> 
T inc(T a) { return ++a; }

关于concept的逻辑运算

依然是concepts库内的约束

template <typename _Tp>
concept signed_integral = integral<_Tp> && is_signed_v<_Tp>;

template <typename _Tp>
concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>;

requires表达式

  1. requires { requirement-seq }
  2. requires ( parameter-list(optional) ) { requirement-seq }

requirements-seq 可以是:简单要求、类型要求、复合要求、嵌套要求.

简单要求

它可以是任意不以 requires 关键字开头的表达式,它断言该表达式是有效的. 只在语言层面上检查该表达式是否有效(编译通过即可),而不会对该表达式进行求值

template <typename T>
concept Addable = requires(T a, T b) { a + b; };  // a + b 可通过编译即可

类型要求

类型要求是以typename关键字开始的要求,紧跟typename的是一个类型名,通常可以用来检查嵌套类型、类模板以及别名模板特化的有效性。如果模板实参替换失败,则要求表达式的计算结果为false

template <typename T, typename T::type = 0>
 struct S;
 template <typename T>
 using Ref = T&;
 template <typename T> concept C = requires
 {
     typename T::inner; // 要求嵌套类型
     typename S<T>; // 要求类模板特化
     typename Ref<T>; // 要求别名模板特化
 };
 
 template <C c>
 struct M {};
 
 struct H {
     using type = int;
     using inner = double;
 };

 M<H> m;

概念C中有3个类型要求,分别为T::inner、S<T>Ref<T>,它们各自对应的是对嵌套类型、类模板特化和别名模板特化的检查。请注意代码中的类模板声明S,它不是一个完整类型,缺少了类模板定义。但是编译器仍然可以编译成功,因为标准明确指出类型要求中的命名类模板特化不需要该类型是完整的。

复合要求

template <class T>
concept Check = requires(T a, T b) {
    { a.clear() } noexcept;  // 支持clear,且不抛异常
    { a + b } noexcept->std::same_as<int>;  // std::same_as<decltype((a + b)), int>
};
template <typename T>
concept C =
    requires(T x) {
    {*x};                                 // *x有意义
    { x + 1 } -> std::same_as<int>;       // x + 1有意义且std::same_as<decltype((x + 1)), int>,即x+1是int类型
    { x * 1 } -> std::convertible_to<T>;  // x * 1 有意义且std::convertible_to< decltype((x *1),T>,即x*1可转变为T类型
};

嵌套要求

由若干条requires构成,每一条都需要满足。

template <class T>
concept Check = requires(T a, T b) {
    requires std::same_as<decltype((a + b)), int>;
};

等同于:

template <class T>
concept Check = requires(T a, T b) {
    { a + b } -> std::same_as<int>;
};

参考资料

C++ Concept_gaoZhuanMing的博客

C++20学习:concept用法介绍_chaos-god的博客

requires表达式 ---C++ 20 模板 知乎-未平

标签:std,concept,integral,C++,template,requires,模板,20Concept
From: https://www.cnblogs.com/Cattle-Horse/p/16637811.html

相关文章

  • C++性能优化指南 pdf
    高清扫描版下载链接:https://pan.baidu.com/s/1Gwc_yVHcJY6trqNodDXLpA点击这里获取提取码《C++性能优化指南》是一本C++代码优化指南。作者精选了他在近30年编程生涯中频......
  • C++ 左值于右值的理解
    定义与区别左值(lvalue,locatorvalue)表示了一个占据内存中某个可识别的位置(也就是一个地址)的对象。即左值指的是可以取地址的变量。区分表达式的左右值属性有一个简......
  • CCF 202009-1 称检测点查询(C++)
    使用结构体struct+自定义sort轻松搞定#include<iostream>#include<bits/stdc++.h>#include<cstdio>usingnamespacestd;intn,X,Y;structpoint{......
  • C++【多线程编程】之【线程安全】
    1.线程安全是什么?在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。2.什么情况......
  • C++各个版本新增对于算法竞赛有用特性
    C++各个版本新增对于算法有用特性C++11auto与decltype类型推导(摘自程序喵大人)autoauto可以让编译器在编译器就推导出变量的类型,话不多说上代码:autoa=10;//10是in......
  • c++ 在项目中创建DLL,并调用
    创建DLL分为两种方法,先介绍第一种一、创建DLL(1)//dll.h#pragmaonce//dll.h#ifndefDLL_H_#defineDLL_H_voidprinthello();voidcallPython();extern"C"_de......
  • C++ 多维数组的访问
    1.可以把一维数组想象成一排士兵,把二维数组想象成一个士兵方阵,把三维数组想象成多个士兵方阵。这样,当你要找其中的一个士兵时,你只要知道他在哪个方阵(从0、1、2中选择),在哪......
  • C/C++全国交通咨询模拟系统
    C/C++全国交通咨询模拟系统全国交通咨询模拟【问题描述】处于对不同目的的旅客对交通工具有不同的要求。例如,因公出差的旅客希望在旅途中的时间尽可能短,出门旅游的游客......
  • C++【多线程编程】之【初识线程创建】
    1.线程创建函数调用pthread_create(句柄、参数、函数入口,函数入口的实参)intpthread_create(....)cppthread类:thread类的创建方法比较简便。但也有很多问题需要考虑......
  • 【c++】线程同步改错题 (互斥体)
     题目:#include<iostream>#include<windows.h>#include<tchar.h>//我想使用线程,让线程按我制定?的方案执行,但是总失败//起床-》吃饭-》工作-》回家-》起床HA......