ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2022-08-29 23:30:10  阅读:229  来源: 互联网

标签: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
来源: https://www.cnblogs.com/Cattle-Horse/p/16637811.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有