现代 C++20 实战高手课
卢誉声
Autodesk 首席工程师
3781 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 29 讲
现代 C++20 实战高手课
15
15
1.0x
00:00/00:00
登录|注册

05|Concepts:解决模板接口的类型与约束定义难题

你好,我是卢誉声。
在上一讲中,我们了解到 C++ 模板不仅具备强大的泛化能力,自身也是一种“图灵完备”的语言,掀起了 C++ 之父 Bjarne Stroustrup 自己都没料到的“模板元编程”这一子领域。
但是,使用模板做泛型编程,最大的问题就是缺少良好的接口,一旦使用过程中出现偏差,报错信息我们难以理解,甚至无从下手。更糟的是,使用模板的代码几乎无法做到程序 ABI 层面兼容。这些问题的根本原因是 C++ 语言本身缺乏模板参数约束能力,因此,既能拥有良好接口、高性能表达泛化,又能融入语言本身是非常困难的。
好在 C++20 标准及其后续演进中,为我们带来了 Concepts 核心语言特性变更来解决这一难题。那么它能为我们的编程体验带来多大的革新?能解决多少模板元编程的历史遗留问题?今天我们一起探究 Concepts。
课程配套代码,点击这里即可获取。

定义 Concepts

首先我们看看 Concepts 是什么,它可不是横空出世的,C++20 为模板参数列表添加了一个特性——约束,采用约束表达式对模板参数进行限制。约束表达式可以使用简单的编译期常量表达式,也可以使用 C++20 引入的 requires 表达式,并且支持约束的逻辑组合,这是对 C++20 之前 enable_if 和 type_traits 的进一步抽象。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

C++20标准引入了Concepts核心语言特性,旨在解决模板接口的类型与约束定义难题。Concepts允许通过约束表达式对模板参数进行限制,提供了一种清晰、易读的约束定义方式,极大地提升了模板函数或类接口的质量和可读性。通过Concepts,开发者可以定义一组由约束组成的具名集合,从而实现对模板参数列表与参数的约束的逻辑分离。这一特性不仅能提升模板函数或类接口的质量,还可以彻底提升代码的可读性。Concepts的高级用法涵盖了requires关键字定义的约束表达式、逻辑操作符的组合用法以及约束顺序规则等重要方面。通过Concepts,C++泛型编程得到了极大的改善,为开发者提供了更加清晰、可复用的泛型编程工具。文章还介绍了合取式、析取式和原子约束的概念,以及requires表达式的使用方法和约束类型的分类。这些内容为读者提供了深入理解Concepts的基础知识和高级用法的重要参考。 Concepts的引入为C++泛型编程带来了重大改进,为开发者提供了更加清晰、可复用的泛型编程工具,同时也改进了约束顺序决策。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《现代 C++20 实战高手课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(4)

  • 最新
  • 精选
  • peter
    请教老师两个问题: Q1:b不是派生类,为什么不报错? BaseClass b; doGetValue(b); b是BaseClass,不是BaseClass的派生类,为什么不报错? Q2:原子约束的f1和f2为什么失败? f1前面加的 requires (S<T>{})表示什么意思?为什么失败? 原子约束有关键字吗?或者说,怎么看出来一个约束是原子约束? 另外,struct S中的constexpr operator什么意思?

    作者回复: Q1:std::is_base_of<T1,T2>严格来说是判断T2是否是T1的派生类或相同类型,而不只是派生类。 Q2:原子约束f1和f2的失败原因是这两个都需要隐式转换成bool,所以原文中说“E的值必须是bool类型,不允许通过任何隐式转换变为bool型”。 F1的requires中的S<T>{}是构造了一个S<T>类型的对象,这个构造对象的语法就是C++11里的统一初始化表达式,相当于S<T>()。然后S这个类有一个operator bool()的成员函数,可以将一个S类型的对象隐式转换成bool类型,这种隐式转换在原子约束中是不允许的。 原子约束是一个概念,没有关键字。如果想要容易理解一点,非严格来说,基本上不是合取或者析取的合法约束一般就是原子约束了,也就是约束的基本组成部分。

    2023-01-25归属地:北京
    4
  • !null
    requiresexport template <typename T1, typename T2> requires requires (T1 x, T2 y) { x + y; } std::common_type<T1, T2> func( T1 arg1, T2 arg2 ) { return arg1 + arg2; } 没看明白requires requires (T1 x, T2 y) { x + y; }是啥意思,如果第一个requires是子句的关键字,requires (T1 x, T2 y) { x + y; }是表达式的话,那不是说这里必须是bool型的吗?x+y不一定是bool型的吧?

    作者回复: 这个requires子句的意思是,只有x+y可以编译成功才匹配这个版本,所以不要求x+y一定是bool型,只要求两个类型可以相加(或者具备operator+重载)。

    2023-08-12归属地:北京
    2
    1
  • !null
    requires 后边接约束表达式,约束表达式应该怎么理解?

    作者回复: requires后边接约束表达式,表示模板参数满足约束表达式要求。约束表达式是一种用于检测类型的表达式,如果将模板参数带入到约束表达式后,约束表达式固定返回常量true ,则表示模板参数满足约束表达式的约束。

    2023-08-16归属地:北京
  • MrDuin
    C++20的新特性,对yC++语言的心里负担更大了。

    作者回复: 可以阅读一下第23讲,了解一下现代C++标准下的“洋葱”理论,希望能够帮助到你。

    2023-03-28归属地:辽宁
收起评论
显示
设置
留言
4
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部