C++20的concepts和ranges如何使用

来源:AI技术网作者:大卫头衔:程序员
导读:本期聚焦于小伙伴创作的《C++20的concepts和ranges如何使用》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++20的concepts和ranges如何使用》有用,将其分享出去将是对创作者最好的鼓励。

C++20的concepts和ranges是泛型编程领域的两大重要革新,前者为模板参数提供了明确的约束机制,后者重新设计了标准库的范围操作体系,两者结合可以大幅简化泛型代码的编写和维护成本。

C++20的concepts和ranges如何使用

concepts的基本使用

concepts的核心作用是约束模板参数的类型特征,避免模板实例化时出现晦涩的编译错误。我们可以通过concept关键字定义约束,也可以在模板参数中直接使用标准库预定义的concepts。

自定义concepts

自定义concepts需要指定要检查的类型特征,比如要求类型支持加法操作、是可比较类型等。以下是一个简单的自定义concepts示例:

#include <iostream>
#include <concepts>

// 定义一个concept,要求类型T支持+操作,且两个T相加的结果还是T类型
template <typename T>
concept Addable = requires(T a, T b) {
    { a + b } -> std::same_as<T>;
};

// 使用Addable约束模板参数
template <Addable T>
T add(T a, T b) {
    return a + b;
}

int main() {
    std::cout << add(1, 2) << std::endl;       // 正确,int满足Addable约束
    // std::cout << add(std::cout, std::cout) << std::endl; // 错误,编译期会提示不满足Addable约束
    return 0;
}

标准库预定义concepts

C++20标准库在<concepts>头文件中提供了大量常用的预定义concepts,比如std::integral(整数类型)、std::floating_point(浮点类型)、std::same_as(两个类型相同)等,可以直接使用减少重复定义。

#include <iostream>
#include <concepts>

// 使用标准库预定义的std::integral约束模板参数
template <std::integral T>
T square(T num) {
    return num * num;
}

int main() {
    std::cout << square(5) << std::endl;       // 正确,int是整数类型
    // std::cout << square(5.2) << std::endl; // 错误,double不满足std::integral约束
    return 0;
}

ranges的基本使用

ranges对传统STL算法进行了封装,支持直接操作范围对象,并且可以实现链式调用,避免了传统算法需要传入迭代器起始和结束位置的繁琐写法。

基础范围操作

ranges算法可以直接接收容器作为操作对象,不需要手动获取begin和end迭代器。以下是一个简单的排序示例:

#include <iostream>
#include <vector>
#include <ranges>
#include <algorithm>

int main() {
    std::vector<int> nums = {3, 1, 4, 1, 5, 9};
    // 使用ranges的sort直接对容器排序
    std::ranges::sort(nums);
    for (int num : nums) {
        std::cout << num << " ";
    }
    // 输出:1 1 3 4 5 9
    return 0;
}

范围适配器与链式调用

ranges提供了大量范围适配器,比如std::views::filter(过滤)、std::views::transform(转换)、std::views::take(取前n个元素)等,这些适配器可以通过管道运算符|实现链式调用,让代码逻辑更清晰。

#include <iostream>
#include <vector>
#include <ranges>

int main() {
    std::vector<int> nums = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    // 过滤出偶数,再将每个偶数乘以2,最后取前3个结果
    auto result = nums 
        | std::views::filter([](int n) { return n % 2 == 0; })
        | std::views::transform([](int n) { return n * 2; })
        | std::views::take(3);
    for (int num : result) {
        std::cout << num << " ";
    }
    // 输出:4 8 12
    return 0;
}

concepts与ranges的结合使用

concepts可以对ranges操作中的参数进行约束,比如约束过滤函数的参数类型、转换函数的返回类型等,让范围操作的类型检查更严格。

以下示例定义了一个concepts约束函数对象,确保过滤函数接收整数并返回布尔值,再将其用于ranges的filter适配器:

#include <iostream>
#include <vector>
#include <ranges>
#include <concepts>

// 定义concept,约束函数对象接收int参数,返回bool
template <typename F>
concept IntFilter = requires(F f, int n) {
    { f(n) } -> std::convertible_to<bool>;
};

// 接收满足IntFilter约束的函数对象,对整数范围进行过滤
template <std::ranges::input_range R, IntFilter F>
auto filter_range(R&& range, F filter_func) {
    return range | std::views::filter(filter_func);
}

int main() {
    std::vector<int> nums = {1, 2, 3, 4, 5};
    // 使用满足IntFilter约束的lambda进行过滤
    auto result = filter_range(nums, [](int n) { return n > 3; });
    for (int num : result) {
        std::cout << num << " ";
    }
    // 输出:4 5
    return 0;
}

使用注意事项

  • concepts约束是编译期检查,不会影响运行时性能,建议在泛型模板中优先使用concepts替代传统的SFINAE写法。
  • ranges的范围适配器返回的是惰性求值的范围对象,只有在实际遍历的时候才会执行操作,不需要担心中间过程产生额外的容器拷贝。
  • 部分旧的编译器对C++20的concepts和ranges支持还不完善,使用前需要确认编译器的支持版本,比如GCC 10+、Clang 13+、MSVC 2019+才基本支持这两个特性。

C++20conceptsranges泛型编程STL修改时间:2026-07-22 22:42:34

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。