在 C++20 中,概念 (Concepts) 是一种用于约束化泛型编程的方法。它们可以用于确保模板参数满足特定的要求,并且可以使代码更易于阅读和维护。 下面是一些使用 concepts 的例子:
#include <concepts>// 定义一个整数类型的概念template<typename T>concept Integral = std::is_integral_v<T>;// 定义一个可以进行加法运算的概念template<typename T>concept Addable = requires(T t, T u) { {t + u} -> std::same_as<T>;};// 使用这两个概念来定义一个通用的加法函数template<Integral T>T add(T a, T b) { return a + b;}// 使用 Addable 概念来定义一个通用的加法函数template<Addable T>auto add(T a, T b) -> decltype(a + b) { return a + b;}
在这个例子中,Integral 是一个概念,它定义了一个必须是整数类型的模板参数。然后,Addable 是另一个概念,它定义了一个可以进行加法运算的模板参数。 最后,我们定义了两个通用的加法函数,分别使用了 Integral 和 Addable 这两个概念来约束模板参数。这样,只有当传入的模板参数满足相应的要求时,这两个函数才能成功编译并运行。 通过这种方式,我们可以利用 concepts 来编写更加健壮、易于理解和维护的代
要调用上述示例中的 add 函数,你可以像下面这样使用:
#include <iostream> int main() { // 调用第一个 `add` 函数 // int result1 = add(3, 5); // ERROR: 编译器不知道调用哪个add,因为两个都符合 // 输出结果 // std: cout << "result1: " << result1 << std::endl; // 调用第二个 `add` 函数 double result2 = add(3.5, 4.7); // 调用第二个add // 输出结果 std::cout << "result2: " << result2 << std::endl; return 0;}
在这段代码中,我们将 add 函数应用于整数和浮点数,第二个调用因为参数类型满足了Addable 这个概念的要求,所以可以正确运行。即符合Addable这个概念的类型T都可以调用第二个add函数。
以下是一个简单的示例,展示如何使用 constraints 和 concepts 在 C++20 中定义一个排序函数:
cpp#include <concepts>#include <iostream>// 定义一个可以进行比较的概念template<typename T>concept Comparable = requires(T t, T u) { {t == u}; {t != u}; {t < u}; {t > u}; {t <= u}; {t >= u};};// 使用这个概念来定义一个通用的排序函数template<Comparable T>void sort(T arr[], int n) { for (int i = 0; i < n - 1; ++i) { for (int j = i + 1; j < n; ++j) { if (arr[j] < arr[i]) { std::swap(arr[i], arr[j]); } } }}int main() { // 定义一个整数数组 int arr[] = {1, 3, 6, 9, 5, 4}; // 尝试调用 `sort` 函数 sort(arr, 6); // 输出数组元素 for (int i = 0; i < 6; ++i) { std::cout << arr[i] << ' '; } return 0;}
在这个例子中,sort 函数是一个模板函数,它接受一个 Comparable 类型的对象数组作为输入,并对其进行排序。由于 Comparable 概念定义了可以进行比较操作的对象类型,所以这个函数可以用于符合Comparable要求的任何类型。
C++20 中的 concepts 提供了以下几个好处: