当前位置: 首页 > news >正文

std::ranges::views::common, std::ranges::common_view

std::ranges::views::common, std::ranges::common_view

C++20 引入的用于将范围适配为“通用范围”的工具,主要解决某些算法需要传统迭代器对(如 begin 和 end 类型相同)的问题。

基本概念

1. 功能
  • 适配传统算法:将范围(range)的迭代器和哨兵(sentinel)类型统一,使其适配需要“迭代器对”的旧式算法(如 C++17 之前的算法)。
  • 类型一致性:确保 begin() 和 end() 返回的迭代器类型相同。
  • 零开销原则:仅在必要时添加类型转换,无额外内存分配。

以下是详细说明和示例:


核心概念

  • 问题背景:C++20 的某些范围(如 split_view)的 begin 和 end 返回的迭代器类型可能不同,但传统算法(如 C++17 前的算法)需要它们类型相同。
  • 解决方案common_view 将范围适配为 begin 和 end 迭代器类型相同的“通用范围”。

std::ranges::common_view

  • 定义template<std::ranges::view V> class common_view : public std::ranges::view_interface<common_view<V>>
  • 适用场景
    • 当原始范围的迭代器和哨兵类型不同,但需要转换为相同类型时。
    • 需要将范围传递给传统算法(如接受 int* 和 int* 的算法)。

语法与参数

1. 语法
auto common_view = range | std::ranges::views::common;
  • range:输入范围(如容器、视图)。

示例 1:适配 split_view
#include <ranges>
#include <vector>
#include <algorithm>
#include <iostream>

int main() {
    std::string str = "hello,world,cpp20";
    auto split = str | std::views::split(',');

    // split 的迭代器和哨兵类型不同,无法直接传递给传统算法
    // 使用 common_view 适配
    auto common_range = split | std::views::common;

    // 现在可以像传统范围一样使用
    for (const auto& part : common_range) {
        for (char c : part) std::cout << c;
        std::cout << '\n';
    }
}

示例 2:传递给传统算法

某些传统算法(如 std::sort)要求 begin() 和 end() 的迭代器类型严格一致,但 C++20 的某些范围(如 std::ranges::iota_view)可能返回不同类型的哨兵:

示例 2:处理子范围
#include <ranges>
#include <vector>
#include <algorithm>
#include <iostream>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    auto reversed = vec | std::views::reverse;

    // 传统算法需要 begin 和 end 类型相同
    // 使用 common_view 适配
    auto common_reversed = reversed | std::views::common;

    // 使用 std::sort(仅示例,反转后排序可能无意义)
    std::ranges::sort(common_reversed); // 需要迭代器类型相同

    for (int x : common_reversed) {
        std::cout << x << ' '; // 输出:1 2 3 4 5(排序后的反转)
    }
}

std::ranges::views::common

  • 定义:范围适配器对象,可通过管道操作符 | 简化 common_view 的创建。
  • 等效操作views::common(r) 等价于 common_view<views::all_t<decltype(r)>>{r}
示例 3:结合管道操作符
#include <ranges>
#include <iostream>
#include <list>
#include <algorithm> // 必须包含此头文件以使用 std::find

int main() {
    std::list<int> lst = {1, 2, 3, 4, 5};
    auto even = lst | std::views::filter([](int x) { return x % 2 == 0; });

    // 使用 views::common 适配
    auto common_even = even | std::views::common;

    // 传递给传统算法 std::find
    if (std::find(common_even.begin(), common_even.end(), 4) != common_even.end()) {
        std::cout << "Found 4\n";
    }
}

注意事项

  1. 性能common_view 可能引入额外开销(如缓存迭代器),需谨慎使用。
  2. 适用性:仅在需要传统迭代器对时使用,现代算法(如 std::ranges::sort)通常不需要。
  3. 生命周期:确保底层范围的生命周期长于 common_view

总结

  • common_view:将 begin 和 end 迭代器类型不同的范围适配为类型相同的通用范围。
  • views::common:通过管道操作符简化 common_view 的创建。
  • 典型场景:与传统算法交互,或需要迭代器类型一致的操作。

相关文章:

  • 小程序渲染之谜:如何解决“加载中...”不消失的 Bug(glass-easel)
  • 跳表实现学习
  • Linux远程工具SecureCRT下载安装和使用
  • Python文件,模块
  • ​【C++设计模式】第二十三篇:观察者模式(Observer)
  • HOT100系列——(普通数组+矩阵)
  • DB-GPT-0.7版本win11安装,最新版本,安装方式变更了
  • ELK traceId 通过A服务调用B服务举例
  • 『MaxKB』MaxKB源码在Docker环境的部署实战
  • 第27周JavaSpringboot电商进阶开发 2.常用功能进阶
  • 要登录的设备ip未知时的处理方法
  • WPF-DataGrid的增删查改
  • 【MapSet】哈希表
  • 麒麟操作系统和统信的区别,上面一般用什么OFFICE,excel软件?
  • Java 什么是线程安全及如何实现线程安全
  • EasyRTC嵌入式音视频通话SDK:基于纯C语言的跨平台实时通信系统设计与实践
  • leetcode144 二叉树的前序遍历 递归法、迭代法
  • 一维数组的增删改查:对元素的影响
  • 解决pip安装uv时下载速度慢
  • 【嵌入式linux】网口和USB热插拔检测
  • 视频丨为救心梗同学缺席职教高考的小伙姜昭鹏完成补考
  • 四大皆空!赛季还没结束,曼城已经吃上“散伙饭”了
  • 南京艺术学院博导、雕塑家尹悟铭病逝,年仅45岁
  • 著名文博专家吴远明因交通事故离世,享年75岁
  • 美国务卿鲁比奥抵达会场,将参加俄乌会谈
  • 侵害孩子者,必严惩不贷!3名性侵害未成年人罪犯今日执行死刑