一个代码示例让你看懂 C++20 Ranges 的惊人魔力

开发
Ranges 库就像是给老旧的迭代器穿上了一件时尚外套,让数据处理变得前所未有的优雅!

亲爱的程序员朋友们!还在为那些又臭又长的迭代器语法抓耳挠腮吗?🤔 别担心,C++20给我们带来了一件超级英雄装备 - Ranges库!它就像是给老旧的迭代器穿上了一件时尚外套,让数据处理变得前所未有的优雅!✨

想象一下,你有一个神奇的百宝箱(也就是我们的容器)🎁,里面装满了各种各样的数据。在过去,要处理这些数据,你可能需要写一堆让人头大的迭代器代码 😫。但现在有了Ranges,一切都变得像魔法一样简单!🪄

来看看这个让人眼前一亮的例子 👀:

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

int main() {
    // 假设这是我们的购物清单和价格 🛒
    std::vector<int> prices = {42, 13, 27, 89, 100, 25, 15};
    
    // 我们想找出所有超过20块的商品,并给它们打个超值八折!💝
    auto expensive_items = prices 
        | std::views::filter([](int price) { return price > 20; })
        | std::views::transform([](int price) { return price * 0.8; });
    
    std::cout << "双11特惠价格: ";  // 改成更有趣的输出文本
    for (double price : expensive_items) {
        std::cout << price << "💰 ";
    }
    // 输出: 33.6💰 21.6💰 71.2💰 80💰 20💰
}

看到了吗?这代码优雅得就像在写诗一样!🎭 使用管道符号 | 把各种操作串在一起,就像在玩乐高积木一样有趣!🎯

让我们再来看个更有趣的例子,这次我们要打造一个超级马里奥世界 🎮:

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

int main() {
    // 召集我们的游戏英雄们!🦸♂️
    std::vector<std::string> players = {
        "Mario", "Luigi", "Peach", "Bowser", "Yoshi"
    };
    
    // 给厉害的角色们升级,变身超级英雄!✨
    auto super_players = players
        | std::views::filter([](const std::string& name) { return name.length() > 4; })
        | std::views::transform([](const std::string& name) { return "Super " + name; });
    
    std::cout << "⭐ 超级英雄登场 ⭐\n";
    for (const auto& name : super_players) {
        std::cout << "🎯 " << name << " 华丽登场!\n";
    }
    // 输出:
    // 🎯 Super Luigi 华丽登场!
    // 🎯 Super Bowser 华丽登场!
}

Ranges库不仅让代码变得清爽可爱,还自带防护罩 🛡️,帮你避开各种讨厌的bug。它就像是你的私人保镖,让你可以放心大胆地写代码,再也不用担心那些烦人的越界问题啦!🎯

最神奇的是,Ranges还是个"懒惰"的小可爱 😴 - 它不会着急忙慌地处理所有数据,而是等到真正需要的时候才开始工作。就像点外卖一样,下单之后厨师会等到外卖小哥来了才开始烹饪,既新鲜又高效!🍳

💡 小彩蛋:Ranges库里还藏着很多好玩的功能等你来发现呢!比如views::zip可以把两个序列像拉拉链一样组合在一起 🤐,views::enumerate则能给每个元素自动编号,就像给小朋友们排队一样!🎪

记住哦,优秀的代码不仅要能跑起来,还要能讲出一个精彩的故事。有了Ranges库这个魔法棒,你的代码也能变成一个充满魔力的童话!✨ 让我们一起用Ranges来创造编程的艺术吧!🎨

Ranges 库的魔法世界 🌈

想象一下,Ranges 库就像是一个神奇的百宝箱 🎁,它不仅让我们告别了那些繁琐的迭代器代码,还给我们带来了一个全新的魔法世界!它就像是给迭代器和算法穿上了一件魔法斗篷,让它们变得更强大,更不容易犯错 ✨

在这个魔法世界里,Range 就像是一个百变小精灵 🧚♀️,它可以变成各种各样的形态:有时候它是一对可爱的迭代器小情侣 [begin, end),手牵手漫步在容器世界里;有时候它是个计数小能手 begin + [0, size),就像 views::counted 那样一步一步数着前进;有时候它还会变成一个带着任务的小侦探 [begin, predicate),像 views::take_while 那样一直探索直到找到特定的线索;甚至有时候它化身无限冒险家 [begin, ..),像 views::iota 那样勇往直前,永不停歇!🚀

这个魔法世界里有两种神奇的魔法:一种是即时魔法(Range 算法)🎯,念咒语后立刻见效;另一种是慵懒魔法(Range 适配器)😴,它会等到真正需要的时候才慢悠悠地发挥作用。就像是点外卖,一个是现成的快餐,另一个是等你真饿了才开始烹饪的私房菜!

而视图(Views)就像是魔法世界里的轻功高手 🥷,动作轻盈(轻量级),来去自如(常数时间复制/移动),还能和其他高手配合使用管道魔法,组成威力强大的组合技!就像这样:

std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// 来看看这个神奇的魔法组合吧!✨
auto magic_numbers = numbers 
    | std::views::filter([](int n) { return n % 2 == 0; })  // 筛选出偶数小精灵 🎭
    | std::views::transform([](int n) { return n * n; });   // 让它们变得更强大!💪

// 看看我们的魔法成果吧!
for (int n : magic_numbers) {
    std::cout << n << " ✨ ";  // 输出:4 16 36 64 100 ✨
}

看!这就是 Ranges 的魔法世界 🎪,它让我们的代码不仅功能强大,还变得像讲故事一样有趣!让我们一起在这个充满魔法的世界里探索吧!🌟

更多魔法组合技!✨

朋友们,想不想学习一些更厉害的 Ranges 魔法组合技呢?🎮 让我们一起来看看这些令人眼前一亮的高级用法吧!

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

int main() {
    // 召唤一队数字小精灵!🔢
    std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    // 来点魔法!让我们从这队小精灵中挑选一些特别的成员 ✨
    auto middle_numbers = numbers 
        | std::views::drop(2)      // 让前面两个小精灵休息一下~ 😴
        | std::views::take(4);     // 只邀请接下来的四个小精灵来玩!🎯
    
    // 让小精灵们手牵手,两个一组排好队 👫
    auto number_pairs = numbers 
        | std::views::chunk(2);    // 两个两个组队,多么整齐呀!
    
    // 来玩个水果超市的游戏!🏪
    std::vector<std::string> fruits = {"🍎苹果", "🍌香蕉", "🍊橙子"};
    // 给每个水果标上价格标签,就像在超市购物一样!
    auto fruit_prices = std::views::zip(fruits, numbers);
    
    // 让我们看看中间那几个活跃的小精灵都有谁!
    std::cout << "✨ 闪亮登场的小精灵们:";
    for (int n : middle_numbers) {
        std::cout << n << " 号小精灵 🌟 ";  // 3 4 5 6 号小精灵闪亮登场!
    }
}

看!这就像是在魔法世界里玩耍一样!🎪 我们可以让数字小精灵们排队(drop 和 take),让它们手牵手组队(chunk),甚至可以让它们和水果小精灵们一起开派对(zip)!每一个视图都像是给小精灵们施展的一个小魔法,而当这些魔法连在一起,就会产生意想不到的精彩效果!✨

这些魔法不仅好玩,还特别实用!就像是给我们的代码加上了魔法翅膀,让它们可以自由翱翔!🦋 而最棒的是,这些魔法都是即用即取的,不会浪费任何魔法能量,就像点外卖一样,需要的时候才会开始准备!🥡

记住,在这个充满魔法的 Ranges 世界里,我们都是快乐的魔法师,可以自由组合这些有趣的魔法,创造出更多精彩的代码!🎨 让我们一起在这个神奇的世界里探索吧!🚀

Range 概念大家族 - 每个都是独当一面的小能手!🌟

嘿,小伙伴们!今天让我们来认识一下 Ranges 库里的几位超级英雄吧!🦸♂️ 他们就像是一个欢乐的大家族,每个成员都有自己的独门绝技!

想象一下,ranges::range 就像是这个家族的族长 👑,它定义了最基本的"范围"概念 - 只要你有开始和结束,就是一个范围!就像是在说"从这棵树到那棵树,这片草地都是我们家的"这样简单!😄

ranges::view 则是家族里最轻盈的舞者 💃,它能以最小的代价复制和移动自己,就像一只灵巧的蝴蝶,轻轻掠过却不会惊动花朵!来看个例子:

std::vector<int> numbers = {1, 2, 3, 4, 5};
auto magical_view = numbers | std::views::filter([](int n) { return n % 2 == 0; });
// 哇!创建视图的成本几乎为零,就像变魔术一样!✨

然后是 ranges::sized_range,这位小可爱可厉害了 📏,它总是能在眨眼间(常数时间)告诉你范围有多大!就像是一个神奇的计数器:

std::vector<int> items = {1, 2, 3};
std::cout << std::ranges::size(items) << " 个宝贝!"; // 瞬间就知道有3个!⚡

至于 ranges::input_range、ranges::forward_range 和 ranges::bidirectional_range,它们就像是三胞胎兄弟 👨👨👦,各有各的本领:

  • 老大只会往前冲(input) 🏃
  • 老二既能往前冲还记得回头看看(forward) 👀
  • 老三更厉害,前后溜达都不在话下(bidirectional) 🔄
std::list<std::string> magic_box = {"🎈", "🎪", "🎭"};
// 双向列表,想往哪走就往哪走,多自在!
for(auto it = magic_box.begin(); it != magic_box.end(); ++it) {
    std::cout << *it << " 耶!";
}

💡 小提示:这些概念就像是魔法契约,在编译时就能确保你的代码和这些范围玩得转!不用担心运行时才发现不合拍的尴尬!🎯

有了这些可爱的概念,我们写代码就像是在魔法世界里玩耍,既安全又有趣!让我们一起用这些神奇的工具,创造出更多精彩的代码吧!✨

Ranges的前世今生 - 一个代码进化的童话故事 📚

嘿,亲爱的程序员朋友们!今天让我来给大家讲一个关于 Ranges 的童话故事~ 🎬

很久很久以前,在代码的世界里,处理数据集合是一件特别麻烦的事情。程序员们不得不写很多繁琐的循环和迭代器代码,就像这样:

std::vector<int> scores = {60, 85, 92, 75, 88};
std::vector<int> passing_scores;
for(auto it = scores.begin(); it != scores.end(); ++it) {
    if(*it >= 80) {
        passing_scores.push_back(*it);
    }
}
// 天啊,好多重复的代码! 😫

直到有一天,D语言的小精灵带来了一个神奇的想法 - "Range"! 🧚♀️ 它告诉C++的设计者们:"嘿,为什么不能让代码读起来像说话一样自然呢?"

与此同时,一位叫 Eric Niebler 的魔法师创造了一个实验性的魔法箱子 - Range-v3 库! 🎁 它展示了一种全新的写代码方式:

// Range-v3 带来的全新魔法! ✨
auto passing_scores = scores 
    | views::filter([](int score) { return score >= 80; });
// 哇!代码突然变得如此优雅! 🎯

这个创意太棒啦!C++标准委员会的智者们看到后,决定把这个魔法带给所有的程序员。他们精心设计了新的魔法咒语,让它变得更加强大:

// 来看看这个处理学生成绩的例子吧!
std::vector<std::pair<std::string, int>> students = {
    {"小明", 95}, {"小红", 85}, {"小华", 75}
};

// 使用现代魔法来找出优秀学生! 🌟
auto honor_students = students
    | std::views::filter([](const auto& student) {
        return student.second >= 90;  // 找出90分以上的学生
    })
    | std::views::transform([](const auto& student) {
        return "🏆 优秀学生: " + student.first;  // 给他们加上小奖杯!
    });

// 看看谁是优秀学生呀~
for(const auto& student : honor_students) {
    std::cout << student << "\n";  // 输出: 🏆 优秀学生: 小明
}

这个魔法最厉害的地方是它的"惰性求值"特性 😴 - 不会立刻处理所有数据,而是在实际需要结果时才进行计算。就像是一个聪明的学生,不会提前做完所有作业,而是按需完成每一步 - 既节省精力,又能确保高效!

而且这个魔法还特别聪明,它能在编译的时候就发现问题:

// 假设我们想统计班级的平均分...
auto average = students
    | std::views::transform([](const auto& student) { 
        return student.second;  // 提取分数
    })
    | std::views::filter([](int score) {  // ❌ 编译器会说:"这样不行哦!"
        return score >= 0;
    });
// 因为 transform 和 filter 的顺序不对,编译器会及时提醒我们! 🚨

从2012年开始,这个魔法经历了漫长的旅程:从实验室里的小火苗 🔥,到2020年最终成为C++20标准库中的一颗璀璨明星 ⭐。现在,它已经成为了每个现代C++程序员的得力助手!

💡 小彩蛋: 知道为什么用管道符号 | 吗?因为它看起来就像是数据流动的管道,让代码读起来像在讲故事一样流畅!

有了这个强大的魔法,我们再也不用写那些繁琐的循环了。让我们一起感谢那些为C++带来这份礼物的魔法师们吧! 🙏✨

责任编辑:赵宁宁 来源: everystep
相关推荐

2024-12-09 15:00:00

C++20代码标记

2021-10-12 07:15:03

C++20特性

2023-11-04 20:00:02

C++20协程

2019-11-25 10:20:54

CSS代码javascript

2017-12-07 15:05:50

全球互联网创新峰会

2022-10-31 07:09:15

拷贝代码项目

2023-03-15 15:54:36

Java代码

2024-01-19 21:07:22

C++20Concepts函数

2021-09-27 10:03:55

装饰器代码

2024-02-05 22:13:50

C++C++20开发

2020-12-21 21:05:29

C++C++20标准草案

2020-12-21 13:33:00

medit编辑器Linux

2024-02-26 16:40:58

2021-07-12 07:08:54

责任链模式对象

2023-11-23 16:46:55

LinuxAWK运维

2017-09-08 15:43:44

编程程序搜索

2021-04-15 07:32:02

java 代码Stream

2024-12-02 10:15:15

2018-05-21 10:20:22

人工智能机器学习神经网络

2018-02-02 11:17:42

IaaSPaaSSaaS
点赞
收藏

51CTO技术栈公众号