cppStream灵感来源于Java的Stream API,使用C++17实现
using namespace yao::stream;
auto result = int_range(1, 101)
>> reduce(std::plus<>{});
std::cout << result.value() << std::endl; // 5050
这是一个最简单的例子,int_range(1, 101)
生成一个整数流,reduce(plus<>{})
对它进行求和,并返回一个optional<int>
,的到结果5050,中间用运算符>>
连接
cppStream的所有组件都在yao::stream
命名空间下
如果定义了宏CPP_STREAM_NO_EXCEPTION
,那么这个库将直接终止程序,而不是抛出异常
就是流水线,与容器不同,延时求值是流最大的特点,只有需要求值,才回去求值
-
流分为有限流和无限流,其中某些无限流是可能无限的无限流,仍然属于无限流,想要检查一个流是否无限,可以调用
stream.endless()
来检查。 -
流也可以分为源和中间流,源就是流中数据的源头,详见下面获取流一节,中间流就是处理流数据的部分,详见下面中间操作一节
using value_type = ...;
值类型,表示这个流包含的元素的类型
template<T>
using value_type_t = ...;
辅助模板,value_type_t<T>
相当于typename T::value_type
decltype(auto) front();
对于流的第一个元素进行访问,在不调用next()
的情况下front() == front()
恒为true
bool next();
检查流是否还有下一个元素,应该总是在front()
调用之前进行检查
bool endless() const;
检查这个流是否是一个无限流
template<typename Builder>
decltype(auto) operator>>(Builder builder) const;
使用Builder
构建下一个流
[提示] 不调用next()
而直接调用front()
结果是未定义的(UB)。
[提示] 当!next()
时调用front()
,结果是未定义的(UB),对于一个无限流进行有限操作,会抛出endless_stream_exception
异常,对于一个无限流进行无限操作,结果是未定义的(UB)。
[提示] 如果需要自定义,后面会讲到如何使用这些类型和函数,但一般而言不要直接调用他们。
from_endless_iterator(First first)
生成一个无限流,流中元素就是*first++
得到的。
from_iterator(First first, Last last)
from(Container const& container)
生成一个有限流,流中包含[first, last)
中所有元素,如果first至last是无法到达的(unreachable),结果是未定义的(UB),因此再调用之前,应该确保他已经被检查。
from_unchecked_iterator(First first, Last last)
from_unchecked(Container const& container)
生成一个无限流,即使first至last是可以到达的(reachable),流中包含[first, last)
中所有元素。
generate(Getter getter)
生成一个无限流,每一个元素都是通过getter()
获得的。
iterate(Init init, Pred pred)
生成一个无限流,其中第一个元素是init
,剩下的每个元素都是init = pred(init)
。
iterate(Init init, Pred0 pred0, Pred pred)
生成一个(可能)无限流,其中第一个元素是init
,剩下的每个元素都是init = pred(init)
,直到!pred0(init)
(不包含)。
iota(IntType first, IntType step = 1)
生成一个无限流,流中的元素类型是IntType
,其中第一个元素是first
,剩下的元素是上一个元素+step
。
int_range(IntType last)
生成一个有限流,流中的元素类型是IntType
,流中元素是[0, last)
。
int_range(IntType first, IntType last)
int_range(IntType first, IntType last, IntType step)
生成一个有限流,流中的元素类型是IntType
,流中元素是[first, last)
,最后每两数之间差值为step
。
empty_stream()
singleton(std::nullopt_t)
生成一个空流,对它调用front()
结果是未定义的(UB)。
singleton(std::optional<T>&& opt)
生成只包含一个元素的流,如果!opt.has_value()
,则生成一个空流。
endless_empty_stream()
endless_singleton(std::nullopt_t)
生成一个无限空流,对它调用next()
和front()
结果都是未定义的(UB)。
endless_singleton(std::optional<T>&& opt)
生成只包含一个重复元素的无限流,如果!opt.has_value()
,则生成一个无限空流。
filter(Pred pred)
过滤流中的元素,过滤一切!pred(elemenet)
的元素。如果一个无限流没有一个元素满足这个pred
,结果是未定义的。
map(Pred pred)
映射流中的操作,流中的元素从element
变为pred(element)
。
take(size_t count)
截短流,流的流仅剩前count
个元素,会把流变为有限流。
skip(size_t count)
跳过前count
个元素。
take_while(Pred pred)
截短流,只要满足!Pred(element)
,就不在向后读取,包括首个不满足该条件的元素。不会改变流的性质,无限流仍然是无限流。
skip_while(Pred pred)
跳过所有元素直到满足!pred(element)
,不包括这个元素。
sort()
sort(Compare compare)
为流进行稳定排序(stable sort),默认的比较器是std::less<>{}
。
如果这是一个无限流,将会抛出endless_stream_exception
reverse()
颠倒流中元素的顺序。如果这是一个无限流,将会抛出endless_stream_exception
。
distinct(Set&& set)
去掉流中重复的元素,使用提供的set
作为缓存器。
peek(Peeker peeker)
偷窥流中的元素,流中每个元素都会调用peek(element)
,只要它被求值。
endless_flat()
flat()
扁平化流,前者得到一个无限流,后者在遇到无限流是抛出endless_stream_exception
。
[未完成:关于"扁平化"的解释]
endless_flat_map(Pred pred)
flat_map(Pred pred)
>> [endless_]flat(pred)
相当于 >> map(pred) >> [endless_]flat()
。
make_endless()
使这个流的endless()
返回true
。
tail_repeat()
当流耗尽,会用最后一个元素作为之后的元素,生成一个无限流。
loop()
当流耗尽,从头开始,如果这是一个空流,结果是未定义的(UB)。
复合操作不使用operator>>
,而是直接把流作为函数的参数。
join_streams(Streams... streams)
连接流,把streams...中的流顺次连接,这些流的类型不必一致,如果其中一个流是无限流,后面的流的元素可能永远不被求值。
combine_streams(Pred pred, Streams... streams)
组合流,吧streams...中流的每个元素调用pred(elements...)
组成一个新的流,这个流的长度取决于最长的那个流,只有所有流都是无限的,生成的流才是无限的。
first()
element_at(size_t pos)
获取第一个元素,或者获取指定位置的元素
for_each(Pred pred)
对于每个元素执行pred(element)
。如果这是一个无限流,将会抛出endless_stream_exception
。
reduce(BiPred biPred)
规约,以第一个元素作为init
,不断执行init = biPred(init, element)
。如果这是一个无限流,将会抛出endless_stream_exception
。
min()
min(Compare compare)
max()
max(Compare compare)
获得最小值和最大值,默认compare
是std::less<>{}
。如果这是一个无限流,将会抛出endless_stream_exception
。
minmax()
minmax(Compare compare)
获得一个pair,first是最小值,second是最大值,默认compare
是std::less<>{}
。如果这是一个无限流,将会抛出endless_stream_exception
。
all_match(Pred pred)
any_match(Pred pred)
none_match(Pred pred)
使用pred(element)
匹配全部/任意/没有元素,返回bool。
count(Counter counter)
计算流的长度,Counter必须重载了前缀++
。如果这是一个无限流,将会抛出endless_stream_exception
。
collect(Container container, Collector collector)
收集流中元素。如果这是一个无限流,将会抛出endless_stream_exception
。
[未完成:关于"收集"的解释]
所有有关类型擦除的组件都在yao::stream::type_erasure
命名空间下
如果你不需要<typeinfo>
中的组件支持你可以定义CPP_STREAM_NO_TYPEINFO
宏来取消
可以存任何元素类型为T
的流,拥有和其他流一样的接口
额外多一个type()
函数,只有在没定义CPP_STREAM_NO_TYPEINFO
宏时才可以使用,返回存的流的类型信息
type_erasure::AnyStream<long> range = int_range(0L, 100L); //手动指定类型
type_erasure::AnyStream range2 = int_range(0, 100); //自动类型推导:AnyStream<int>