Logo
Section 1 / 5

概念的使用

了解 C++ 概念的主要应用场景。

导入

概念的使用

了解 C++ 概念的主要应用场景。

概念是C++20引入的主要新特性之一。概念是对模板的扩展,允许程序员直接表达其意图。根据C++之父本贾尼·斯特劳斯特鲁普的说法:“概念使模板如最初设想的那样变得完整。”

C++概念可以在哪些地方使用?

  • 我们可以使用概念通过布尔谓词对模板参数进行编译时验证。检查在调用点执行,因此错误信息比以往在实例化时出现时更加清晰易懂。

  • 我们还可以基于类型属性实现函数分派。

  • 通过概念,我们可以同时要求语法和语义条件。在语法要求方面,想象一下可以强制任何类的API中存在某些特定函数。例如,我们可以创建一个名为 Car 的概念,要求其必须包含 accelerate 函数,如下代码所示。

...
Uses of Concepts
1#include<concepts> 2template<typename C> 3concept Car = requires(C car) { 4 car.accelerate(); 5};

在本课程中,我们主要会遇到仅包含少量要求的例子。尽管目前尚无编写优质概念的最佳实践(因为这是一个较新的特性),但C++社区已达成共识:好的概念不应规定最少数量的要求;它们必须满足所有条件。这是为了确保我们不会无意中创建出偶然满足的概念。

如果我们能以语义上一致的方式完整地建模某个概念,最终将得到更广泛可用的概念。如果第一次尝试未能达到这一目标,也完全没问题。我们终会做到!

不过需要说明的是,在本课程中,我们通常会看到一些不完整的概念,以便专注于它们的特定部分。

语法要求

我们放在 requires 子句中的任何内容都描述了用于建模概念的类型的语法要求。

课程后续将详细讨论其语法。

语义要求

概念不仅表达语法要求,还表达语义要求。但必须承认,C++概念无法直接表达所有语义要求,至少目前还不能。

一些语义要求与数学公理相关,比如结合律或交换律。

1a + b == b + a // 交换律 2(a + b) + c == a + (b + c) // 结合律

这些可以通过代码来表达。事实上,我们已经部分实现了这一点。

而像操作的时间或空间复杂度这类要求,则无法用代码表达。我们必须依赖代码注释或库文档来说明。

如果想寻找示例,值得查看标准库。例如 std::equality_comparable。

注意:你可以在官方C++文档中了解更多关于 std::equality_comparable 概念的信息。

它要求:

  • 传入类型的两个相等比较运算符具有交换性。
  • == 运算符具有对称性、传递性和自反性。
  • 当且仅当对于任意类型为 const std::remove_reference_t<T> 的值 t 和任意类型为 const std::remove_reference_t<U> 的值 u,以及当 C 为 std::common_reference_t<const std::remove_reference_t<T>&, const std::remove_reference_t<U>&>* 时,满足 bool(t == u) == bool(C(t) == C(u)),才定义 equality_comparable_with<T, U>。

简介

C++ 概念背后的动机