C++20 Concepts:提高代码可读性与安全性的实践

C++20 引入的 Concepts 概念为模板编程提供了强大而灵活的约束机制。相比于传统的 SFINAE 技术,Concepts 可以让编译器在编译时就判断模板参数是否满足特定的性质,从而产生更友好的错误信息,并且在代码中显式表达意图。下面将通过几个常见场景,展示如何利用 Concepts 提升代码质量。

  1. 定义基本概念
    Concepts 本身可以像普通类型一样定义。常见的有 IntegralFloatingPoint 等。
    
    #include <concepts>

template concept Integral = std::is_integral_v

; template concept FloatingPoint = std::is_floating_point_v ; “` 使用 `concept` 关键字后,可以直接在模板参数列表中约束。 2. **包装已有类型的约束** 有时我们需要一个组合概念,例如“数值类型”。 “`cpp template concept Number = Integral || FloatingPoint; “` 这样只要类型满足 `Integral` 或 `FloatingPoint`,就算通过 `Number`。 3. **使用 Concepts 的函数模板** 传统模板在类型不匹配时会报错,错误信息往往难以理解。Concepts 让错误更具体。 “`cpp #include #include template T add(T a, T b) { return a + b; } “` 如果调用 `add(“a”, “b”)`,编译器会提示 `T` 必须满足 `Number`,而不是模糊的“no matching function”。 4. **概念化容器** C++20 标准库中已经包含了 `std::ranges::input_range`、`std::ranges::output_range` 等概念。我们可以自定义一个“可遍历”概念。 “`cpp #include template concept Iterable = requires(C c, typename std::decay_t ::value_type v) { { std::begin(c) } -> std::input_iterator; { std::end(c) } -> std::sentinel_for; { *std::begin(c) } -> std::convertible_to ; }; “` 使用示例: “`cpp template void print_all(const C& container) { for (const auto& elem : container) { std::cout T max(T a, T b) { return a > b ? a : b; } template T max(T a, T b) { return a > b ? a : b; // 也可以使用 std::max } “` 编译器根据参数类型自动选择合适的实现。 6. **与 constexpr 的配合** Concepts 也能在 `constexpr` 语境中使用,提升编译期计算的可读性。 “`cpp constexpr auto factorial = [](auto n) -> decltype(auto) { static_assert(std::integral, “factorial requires integral type”); if (n #include template void quick_sort(std::vector & vec) { std::sort(vec.begin(), vec.end()); } “` 调用 `quick_sort` 时,若传入自定义类型,该类型必须满足 `std::totally_ordered`,即提供 `

发表评论