导语
在正式分析libunifex之前,我们需要了解一部分它依赖的基础机制,方便我们更容易的理解它的实现。本篇介绍的主要内容是关于c++linq的,可能很多读者对c++的linq实现会比较陌生,但说到C#的linq,大家可能马上就能对应上了。没错,c++的linq就是在c++下实现类似C#linq的机制,本身其实就是在定义一个特殊的DSL,相关的机制已经被使用在c++20的ranges库,以及不知道何时会正式推出的execution库中,作为它们实现的基础之一。本篇我们主要围绕已进入标准的ranges实现来展开关于c++linq的探讨,同时也将以ranges的一段代码为起点,逐步展开本篇的相关内容。
一、从ranges示例说起
ranges是c++20新增的特性,很好的弥补了c++容器和迭代器实现相对其他语言的不便性。它的使用并不复杂。我们先来看一个具体的例子:autoconstints={0,1,2,3,4,5};autoeven_func=[](inti){returni%2==0;};autosquare_func=[](inti){returni*i;};autotmpv=ints
std::views::filter(even_func)
std::views::transform(square_func);for(inti:tmpv){std::couti;}初次接触,相信很多人都会疑惑:
这是如何实现的?
c++里也能有linq?
为什么这种表达虽然其他语言常见,在c++里存在却显得有点格格不入?
从逻辑上来讲,上述代码起到的是类似语法糖的效果,linq表达:ints
std::views::filter(even_func)
std::views::transform(square_func);
等价函数调用方式为:std::views::transform(std::views::filter(ints,event_func),square_func);所以表面上来看,它似乎是通过特殊的操作符重载来规避掉了多层函数嵌套表达,让代码有了更好的可读性,表达更简洁了。
但这里的深层次的设计其实并没有那么简单,这也是大家读ranges相关的文章,会发现这“语法糖”居然还会带来额外的好处,最终