-
Notifications
You must be signed in to change notification settings - Fork 3
StreamAPI
Cranberries Libraries の最新作ができました。 今回はストリームAPIライブラリででっす!
Java8のStream APIが一番近い。 C#のLINQも近い。 C++ではRange Adaptorが近い。
ストリームはイテレータのラップ。 レンジに対する処理を連続的に記述できる。
ストリームの利用には、3段階ある。 中間処理は遅延評価され、 終端処理が呼ばれたときに評価される。
- ストリームの構築
- 中間処理
- 終端処理
また、ストリームには無限ストリームと有限ストリームがある。 有限ストリームにはすべてのオペレーションが適用できるが、 無限ストリームは適用できるオペレーションが制限される。 これはオペレーションがレンジを要求することによる制限である。
ストリームのオペレーションはoperator >>によるメソッドチェインまたは、
メンバ関数のメソッドチェインによって行う。
ストリーム
>> 中間処理1()
>> 中間処理2()
>> 中間処理3()
>> 終端処理()
;
または、
ストリーム
.中間処理1()
.中間処理2()
.中間処理3()
.終端処理()
;
- 有限ストリーム
有限の要素を持つストリーム。 レンジを持つのでレンジ特有の操作(リバースやソート、シャッフルなど)を含めて、 すべての中間処理・終端処理が行える。
- 無限ストリーム
無限の要素を持つストリーム。 Generate(生成関数による無限列)、 Iterate(漸化式による数列)、 Cyclic(範囲繰り返し数列)、 Random(乱数列)、 Distribution(分布乱数列) などがある。 レンジを要求する操作、 すべての終端処理が行えない。
ストリームの構築方法は主に3つある。
- 有限ストリームのコンストラクタによる構築
- make_streamクラスのstatic関数よる構築
- stream_builderによる構築
stream<int>{ 1,2,3,4 }; // initializer_listによるコンストラクタ
std::vector<int> v{1,2,3,4};
stream<int>{ v }; // rangeを引数に取るコンストラクタ
stream<int>{ v.begin(), v.end() }; // イテレータペアを引数に取るコンストラクタmake_streamクラスのstatic関数をつかって、
色々なストリームを生成できる。
- make_stream::of
有限ストリームの構築。
値のセットからストリームを作る。 イテレータペアを引数に取るものと、初期化子リストを引数に取るものがある。
template <
typename Iterator,
typename T = typename std::decay_t<Iterator>::value_type
>
static
stream<T>
of(Iteraotr&& first, Iterator&& last);
template < typename T >
static
stream<T>
of(std::initializer_list<T> il);Example)
std::vector<int> vec{ 1, 2, 3 };
make_stream::of( vec.begin(), vec.end() );
make_stream::of( { 1, 2, 3 } );- make_stream::from
有限ストリームの構築。
レンジからストリームを生成する。
Rangeはbegin, endでイテレータを取れる必要がある。
また、stringをsplitしてストリームを構築することができる。
template <
typename Range,
typename T = typename std::decay_t<Range>::value_type
>
static
stream<T>
from(Range&&);Example)
std::vector<int> vec{ 1, 2, 3 };
make_stream::from( vec );
make_stream::from( "123:456:789" | streams::split(":") ); // { "123", "456", 789" }- make_stream::range
有限ストリームの構築。
初期値(第1引数)から始まり、 上界(第2引数)まで、 step(第3引数デフォルト値は1)ずつ増えていく有限数列を生成できる。
template < typename T >
static
stream<T>
range(T first, T upper_bound, T step = T{1});make_stream::range(1,10); // { 1, 2, ... , 9 }
make_stream::range(1,10,2); // { 1, 3, 5, 7, 9 }- make_stream::Iterate
無限順次ストリームの構築。
漸化式による列生成。 初期値(第1引数)を与え、 前項を引数に取る関数(第2引数)により次項を決定していく。
template <
typename T,
typename UnaryOperator Op
>
static
IterateStream<T,UnaryOperator>
iterate(T seed_, UnaryOperator operator_);Example)
// フィボナッチ数列の生成
make_stream::iterate( 1,
[ prev1 = 0 , prev2 = 0]( auto&& a ) mutable {
return prev2 = prev1, prev1 = a, prev1 + prev2;
}); // { 1, 1, 2, 3, 5, 8, 13, ... }
- make_stream::counter
無限順次ストリームの構築。
初期値を指定して、インクリメントしていく。 ほぼiterateのラップであるが、初期値をインクリメントするのでiterateより速い可能性がある。
template < typename Iterable >
static
CountingStream<Iterable>
counter(Iterable seed);- make_stream::generate
無限順次ストリームの構築。
Supplier(引数)によって生成される値による無限列の生成。
template < typename Supplier >
static
GenerateStream<std::result_of_t<Supplier()>,Supplier>
generate(Supplier supplier);Example)
// { { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 }, ... }
make_stream::generate(
[]{ return std::vector<int>{1,2,3}; }
);- make_stream::repeat
無限順次ストリーム、または有限ストリームの構築。
特定の値を繰り返す無限列を生成する。 繰り返しに使用する値(第1引数)を指定する。 また、繰り返し回数(第2引数)を指定して有限ストリームを生成するオーバーロードもある。
template < typename T >
static
GenerateStream<T,Generator<T>>
repeat(T val);
template < typename T >
static
stream<T>
repeat(T val, std::size_t lim);Example)
make_stream::repeat(1); // { 1, 1, 1, ... }
make_stream::repeat(1, 4); // { 1, 1, 1, 1 }- make_stream::cyclic
無限順次ストリームの構築。
範囲繰り返し列の生成。 繰り返す範囲を初期化子リスト、レンジ、イテレータペアのいずれかで指定する。
template < typename T >
static
CyclicStream<T>
cyclic(std::initializer_list<T> il);
template < typename Range >
static
CyclicStream<typename std::decay_t<Range>::value_type>
cyclic(Range&& range);
template < typename Iterator >
static
CyclicStream<typename std::decay_t<Iterator>::value_type>
cyclic(Iterator&& first, Iterator&& last);Example)
make_stream::cyclic( { 1, 2, 3 } ); // { 1, 2, 3, 1, 2, 3, 1, ... }
std::vector<int> vec{ 1, 2, 3 };
make_stream::cyclic( vec );
make_stream::cyclic( vec.begin(), vec.end() );###乱数列・分布乱数列の無限ストリーム
乱数列を生成するためには、乱数生成エンジンが必要である。 乱数生成エンジンを使うには初期シードが必要である。 したがって、乱数ストリーム・分布乱数ストリームにはこれらの情報を渡してやる必要がある。
乱数生成エンジンを指定するにはテンプレート引数を用いる。
指定しなければ、std::mt19937になる。
Example)
make_stream::random<std::default_random_engine>();初期シードは引数の最後に指定する。
指定しなければ、std::random_deviceによって生成される。
Example)
make_stream::random( 0 );分布乱数ストリームでは返り値の型を指定する事ができる。
第1テンプレート引数で指定できる。
この仕様のため、エンジンを指定する場合にはちょいとややこしい。
例えば、exponential_distributionをラップしたストリームの場合を考える。
exponential_distributionは
template <class RealType = double> class exponential_distribution;のように宣言されている。
RealTypeを省略するとdoubleになる。
ストリームもこれに習っている。
make_stream::exponential_distは次のように宣言されており、
Engineの指定をする場合、
RealTypeの指定を省略できない。
template <
typename Engine = std::mt19937,
typename RealType = double,
typename Init,
typename Seed = unsigned
>
static
GenerateStream<
RealType,
GeneralizedDistributionGenerator<
RealType,
Init,
std::exponential_distribution<RealType>,
Engine,
Seed
>
>
exponential_dist
(
Init exponent,
Seed seed = std::random_device{}()
);乱数列ストリームはGenerateStreamになる、
第2テンプレート引数はxxx_distributionをラップした
GeneralizedDistributionGeneratorクラスが指定されます。
大抵の場合長いので以後、GeneralizedDistributionGeneratorの引数は省略します。
- make_stream::random
無限乱数ストリームの構築。
std::randomのラップ。
必要な場合、
テンプレート第1引数でエンジンを指定し、
引数でシードを指定する。
template <
typename Engine = std::mt19937,
typename Seed = unsigned
>
GenerateStream<Seed, Engine>
make_stream::random
(
Seed&& seed = std::random_device{}()
);- make_stream::uniform_dist
無限乱数ストリームの構築。
std::uniform_int_distribution, std::uniform_real_distributionのラップ。
ResultTypeがintegral_typeの場合はstd::uniform_int_distributionに、
floating_pointの場合は std::uniform_real_distributionが自動的に選択されます。
範囲の指定がそのままResultTypeの推定になるので、テンプレート引数の指定を省略できます。
template <
typename ResultType,
typename Engine = std::mt19937,
typename Seed = unsigned
>
static
GenerateStream<
ResultType,
UniformGen</* 省略 */>
>
uniform_dist
(
ResultType min,
ResultType max,
Seed seed = std::random_device{}()
);Example)
make_stream::uniform_dist( 1, 10 ); // uniform_int_distribution<int>(1, 10) による分布乱数列
make_stream::uniform_dist( 1ull, 10ull ); // uniform_int_distribution<unsigned long long>(1, 10) による分布乱数列
make_stream::uniform_dist( 1.0, 2.0 ); // uniform_real_distribution<double>(1.0, 2.0) による分布乱数列
make_stream::uniform_dist<long double>(0.0, 1.0); // uniform_real_distribution<long double>(0.0, 1.0) による分布乱数列- make_stream::bernoulli_dist
無限乱数ストリームの構築。
std::bernoulli_distributionのラップ。
第1引数で確率を指定、必要に応じて第2引数でシードを指定する。
bernoulli_distributionは生成される値はboolしかありえないので、
第1テンプレート引数でエンジンを指定できる。
template <
typename Engine = std::mt19937,
typename Init,
typename Seed = unsigned
>
static
GenerateStream<
bool,
GeneralizedDistributionGenerator</* 省略 */>
>
bernoulli_dist
(
Init probability,
Seed seed = std::random_device{}()
);Example)
auto coin_flips = make_stream::bernoulli_dist(0.5);- make_stream::poisson_dist
無限乱数ストリームの構築。
poisson_distributionのラップ。
第1引数で平均値を指定、必要に応じて第2引数でシードを指定する。
template <
typename IntType = int,
typename Engine = std::mt19937,
typename Init,
typename Seed = unsigned
>
static
GenerateStream<
IntType,
GeneralizedDistributionGenerator</* 省略 */>
>
poisson_dist
(
Init avarage,
Seed seed = std::random_device{}()
);Example)
make_stream::poisson_dist(1.0);
make_stream::poisson_dist<long>(1.0)- make_stream::exponential_dist
無限乱数ストリームの構築。
exponential_distributionのラップ。
第1引数で指数を指定、必要に応じて第2引数で初期シードを指定する。
template <
typename RealType = double,
typename Engine = std::mt19937,
typename Init,
typename Seed = unsigned
>
static
GenerateStream<
RealType,
GeneralizedDistributionGenerator<
RealType,
Init,
std::exponential_distribution<RealType>,
Engine,
Seed
>
>
exponential_dist
(
Init exponent,
Seed seed = std::random_device{}()
);Example)
make_stream::exponential_dist(1.0);- make_stream::gamma_dist
無限乱数ストリームの構築。
gamma_distributionのラップ。
第1引数で形状母数を、
第2引数で尺度母数を、
必要に応じて第3引数で初期シードを指定する。
template <
typename RealType = double,
typename Engine = std::mt19937,
typename Init,
typename Seed = unsigned
>
static
GenerateStream<
RealType,
GeneralizedDistributionGenerator</* 省略 */>
>
gamma_dist
(
Init shape_param,
Init scale_param,
Seed seed = std::random_device{}()
)Example)
// 形状母数1.0, 尺度母数1.0 によるガンマ分布乱数列
make_stream::gamma_dist( 1.0, 1.0 );- make_stream::weibull_dist
無限乱数ストリームの構築。
weibull_distributionのラップ。
第1引数で形状母数を、
第2引数で尺度母数を、
必要に応じて第3引数で初期シードを指定する。
template <
typename RealType = double,
typename Engine = std::mt19937,
typename Init,
typename Seed = unsigned
>
static
GenerateStream<
RealType,
GeneralizedDistributionGenerator</* 省略 */>
>
weibull_dist
(
Init shape_param,
Init scale_param,
Seed seed = std::random_device{}()
)Example)
// 形状母数1.0, 尺度母数1.0 によるWeibull分布乱数列
make_stream::weibull_dist( 1.0, 2.0 );- make_stream::extreme_value_dist
無限乱数ストリームの構築。
extreme_value_distributionのラップ。
第1引数で位置変数を、
第2引数で尺度変数を、
必要に応じて第3引数で初期シードを指定する。
template <
typename RealType = double,
typename Engine = std::mt19937,
typename Init,
typename Seed = unsigned
>
static
GenerateStream<
RealType,
GeneralizedDistributionGenerator</* 省略 */>
>
extreme_value_dist
(
Init location_param,
Init scale_param,
Seed seed = std::random_device{}()
)Example)
// 位置変数 1.0, 尺度変数 2.0 の極値分布乱数列
make_stream::extreme_value_dist( 1.0, 2.0 );- make_stream::normal_dist
無限乱数ストリームの構築。
normal_distributionのラップ。
第1引数で平均値を、
第2引数で標準偏差を、
必要に応じて第3引数で初期シードを指定する。
template <
typename RealType = double,
typename Engine = std::mt19937,
typename Init,
typename Seed = unsigned
>
static
GenerateStream<
RealType,
GeneralizedDistributionGenerator</* 省略 */>
>
normal_dist
(
Init average,
Init standard_deviation,
Seed seed = std::random_device{}()
)Example)
// 平均値 5.0, 標準偏差 1.0 の正規分布乱数列
make_stream::normal_dist( 5.0, 1.0 );- make_stream::lognormal_dist
無限乱数ストリームの構築。
lognormal_distributionのラップ。
第1引数で平均値を、
第2引数で標準偏差を、
必要に応じて第3引数で初期シードを指定する。
template <
typename RealType = double,
typename Engine = std::mt19937,
typename Init,
typename Seed = unsigned
>
static
GenerateStream<
RealType,
GeneralizedDistributionGenerator</* 省略 */>
>
lognormal_dist
(
Init average,
Init standard_deviation,
Seed seed = std::random_device{}()
)Example)
// 平均値 3.14, 標準偏差 1.0 の対数正規分布乱数列
make_stream::lognormal_dist( 3.14, 1.0 );- make_stream::chi_squared_dist
無限乱数ストリームの構築。
chi_squared_distributionのラップ。
第1引数で自由度、 必要に応じて第2引数で初期シードを指定する。
template <
typename RealType = double,
typename Engine = std::mt19937,
typename Init,
typename Seed = unsigned
>
static
GenerateStream<
RealType,
GeneralizedDistributionGenerator<
RealType,
Init,
std::chi_squared_distribution<RealType>,
Engine,
Seed
>
>
chi_squared_dist
(
Init degree_of_freedom,
Seed seed = std::random_device{}()
)Example)
// 自由席 1.0 による カイ2乗分布乱数列
make_stream::chi_squared_dist( 1.0 );- make_stream::cauchy_dist
無限乱数ストリームの構築。
cauchy_distributionのラップ。
第1引数で位置変数を、
第2引数で尺度変数を、
必要に応じて第3引数で初期シードを指定する。
template <
typename RealType = double,
typename Engine = std::mt19937,
typename Init,
typename Seed = unsigned
>
static
GenerateStream<
RealType,
GeneralizedDistributionGenerator</* 省略 */>
>
cauchy_dist
(
Init location_param,
Init scale_param,
Seed seed = std::random_device{}()
)Example)
// 位置変数 1.0, 尺度母数 1.0のコーシー分布による無限乱数列
make_stream::cauchy_dist( 1.0, 1.0 ) >> taken( 3 ) >> print_to();- make_stream::fisher_f_dist
無限乱数ストリームの構築。
fisher_f_distributionのラップ。
第1引数で一つ目の自由度、
第2引数で二つ目の自由度、
必要に応じて第3引数で初期シードを指定する。
template <
typename RealType = double,
typename Engine = std::mt19937,
typename Init,
typename Seed = unsigned
>
static
GenerateStream<
RealType,
GeneralizedDistributionGenerator</* 省略 */>
>
fisher_f_dist
(
Init degree_of_freedom1,
Init degree_of_freedom2,
Seed seed = std::random_device{}()
)Example)
自由度 5, 10 のフィッシャーのf分布による無限乱数列
make_stream::fisher_f_dist( 5, 10 )- make_stream::student_t_dist
無限乱数ストリームの構築。
student_t_distributionのラップ。
第1引数で自由度、
必要に応じて第2引数で初期シードを指定する。
template <
typename RealType = double,
typename Engine = std::mt19937,
typename Init,
typename Seed = unsigned
>
static
GenerateStream<
RealType,
GeneralizedDistributionGenerator</* 省略 */>
>
student_t_dist
(
Init degree_of_freedom,
Seed seed = std::random_device{}()
)Example)
// 自由度 1.0 のスチューデントのt分布による無限乱数列
make_stream::student_t_dist( 1.0 );- make_stream::generate_canonical
無限乱数ストリームの構築。
generate_canonicalのラップ。
[ 0.0, 1.0 ) の区間に展開された一様分布乱数を生成する。
template <
typename RealType = double,
size_t Bits = std::numeric_limits<RealType>::digits,
typename Engine = std::mt19937,
typename Seed = unsigned
>
static
GenerateStream<
RealType,
CanonicalGen<RealType,Bits,Engine>
>
generate_canonical
(
Seed seed = std::random_device{}()
)stream_builder<T>クラステンプレートを用いて、
手動で逐次値を追加した後ストリームを構築することができます。
stream_builderクラスには値を追加するために、
addメンバ関数が用意されています。
または、operator<<を用いて値を追加する事ができます。
stream_builder<T>からstream<T>を構築するには、
buildメンバ関数を用います。
または、<< buildとすることもできます。
Example)
stream<int> x = stream_builder<int>{}
.add(1)
.add(2)
.add(3)
.build();
stream<int> y = stream_builder<int>{}
<< 1 << 2 << 3 << 4
<< build;- 中間処理
- 非レンジ要求処理
- レンジ要求処理
- 終端処理
無限ストリームに適用できるのは、非レンジ要求の中間処理のみ。 有限ストリームにはすべてのオペレーションが適用できる。
中間処理は終端処理が呼ばれるまで評価が遅延される。
アダプター形式とメンバ関数形式の両方がある。 中間処理の場合は名前が異なる。
| オペレーション形式 | 関数名が動詞 | 関数名が形容詞 |
|---|---|---|
| アダプター形式 | 関数名は受動態 | 関数名は副詞形 |
| メンバ関数形式 | 関数名は原型 | 関数名は形容詞 |
Example)
| オペレーション形式 | 関数名が動詞 | 関数名が形容詞 |
|---|---|---|
| アダプター形式 | filtered | uniquely |
| メンバ関数形式 | filter | unique |
中間処理の中で非レンジ要求処理だけが無限ストリームに適用できる。
フィルター、写像、マージ、結合、重複削除など20種類。
- filter(filtered)
条件に一致する要素を取り除く。
引数にストリーム要素型を受け取りboolを返す関数オブジェクトを渡す。
Example)
make_stream::range(1,9) // { 1,2,3,4,5,6,7,8 }
>> filtered( [](auto&& a){ return a%2 ==0; } ) // { 1,3,5,7 }
;
make_stream::range(1,9)
.filter( [](auto&& a){ return a%2 ==0; } )
;
make_stream::counter(1) // [ 1,2,3,.. )
>> filtered( [](auto&& a){ return a%2 ==0; } ) // [ 1,3,5,... )
;- stride(strided)
要素をn刻みで選択する。
引数で刻み幅nを指定する。
Example)
make_stream::range(1,9) // { 1,2,3,4,5,6,7,8 }
>> strided( 2 ) // { 1,3,5,7 }
;
make_stream::range(1,9) // { 1,2,3,4,5,6,7,8 }
.stride( 3 ) // { 1,4,7 }
;
make_stream::counter(1) // [ 1,2,3,... )
>> strided( 3 ) // [ 1,4,7,... )
;- drop(dropped)
先頭のn要素を取り除く。
引数で要素数nを指定する。
Example)
make_stream::range(1,9) // { 1,2,3,4,5,6,7,8 }
>> dropped( 4 ) // { 5,6,7,8 }
;
make_stream::range(1,9) // { 1,2,3,4,5,6,7,8 }
.drop( 3 ) // { 4,5,6,7,8 }
;
make_stream::counter(1) // [ 1,2,3,4,5... )
>> dropped( 4 ) // [ 5,6,7,... )
;- drop_while(dropped_while)
条件を満たさなくなるまで先頭要素を取り除く。
引数でストリームの要素型を引数にとりboolを返す関数オブジェクトを渡す。
Example)
make_stream::range(1,9) // { 1,2,3,4,5,6,7,8 }
>> dropped_while( [](auto&& a){ return a < 5; } ) // { 5,6,7,8 }
;
make_stream::range(1,9) // { 1,2,3,4,5,6,7,8 }
.drop_while( [](auto&& a){ return a < 5; } ) // { 5,6,7,8 }
;
make_stream::cyclic({ 1,2,3 }) // [ 1,2,3,1,2,3,... )
>> dropped_while( [](auto&& a){ return a < 3; } ) // [ 3,1,2,3,1,2,3,... )
;- take(taken)
先頭のn要素を選択する。
要素数nを引数で指定する。
このオペレーションを無限ストリームに適用すると有限ストリームに変換される。
Example)
make_stream(1,9) // { 1,2,3,4,5,6,7,8 }
>> taken( 3 ) // { 1,2,3 }
;
make_stream::range(1,9)
.take( 5 ) // { 1,2,3,4,5 }
;
make_stream::counter(1) // [ 1,2,3,... )
>> taken( 4 ) // { 1,2,3,4 }
;- take_while(taken_while)
条件を満たさなくなるまで先頭要素を選択する。
引数でストリームの要素型を引数にとりboolを返す関数オブジェクトを渡す。
このオペレーションを無限ストリームに適用すると有限ストリームに変換される。
Example)
make_stream::range(1,9) // { 1,2,3,4,5,6,7,8 }
>> taken_while( [](auto&& a){ return a < 4; } ) // { 1,2,3 }
;
make_stream::range(1,9) // { 1,2,3,4,5,6,7,8 }
.take_while( [](auto&& a){ return a < 4; } ) // { 1,2,3 }
;
make_stream::counter(1) // [ 1,2,3,... )
>> taken_while( [](auto&& a){ return a < 4; } ) // { 1,2,3 }
;- slice(sliced)
m番目の要素からn番目の要素を選択する。
引数で位置n,mを指定する。
このオペレーションを無限ストリームに適用すると有限ストリームに変換される。
Example)
make_stream(1,9) // { 1,2,3,4,5,6,7,8 }
>> sliced( 2, 5 ) // { 2,3,4,5 }
;
make_stream::range(1,9) // // { 1,2,3,4,5,6,7,8 }
.slice( 3,3 ) // { 3 }
;
make_stream::counter(1) // [ 1,2,3,... )
>> sliced( 3, 5 ) // { 3,4,5 }
;- transform(transformed)
全単射。全要素に関数を適用し、返り値により要素を書き換える。
引数でストリームの要素型を引数にとり、何らかの値を返す関数オブジェクトを指定する。
Example)
make_stream::range(1,5) // { 1,2,3,4 }
>> transformed( [](auto&& a){ return a*2; } ) // { 2,4,6,8 }
;
make_stream::range(1,5) // { 1,2,3,4 }
.transform( [](auto&& a){ return a*2; } ) // { 2,4,6,8 }
;
make_stream::counter(1) // [ 1,2,3,... )
>> transformed( [](auto&& a){ return a*2; } ) // [ 2,4,6,... )
;- transform_to(transformed_to)
要素をstatic_castにより型変換する。
std::stringが指定された場合はstd::to_stringを候補に加えたADLによってto_stringされる。
テンプレート引数で変換先の型を指定する。
make_stream::range(1,4) // { 1,2,3 }
>> transformed_to<std::string>() // { "1", "2", "3" }
;
make_stream::range(1,3) // { 1,2,3 }
.transform_to<double>() // { 1.0, 2.0, 3.0 }
;
make_stream::counter(1) // [ 1,2,3,... )
>> transformed_to<std::string>() // [ "1", "2", "3", ... )
;- flat_transform(flat_transformed)
一対多の写像。ひとつの要素から複数の要素に変換する。
引数でストリームの要素型を引数にとり、多値を返す関数オブジェクトを指定する。 関数オブジェクトが返すことが許可される型は
- 配列型
- レンジコンテナ
- tuple
の3つである。
レンジコンテナとはstd::begin(),std::end()でイテレータを取得できるコンテナを指す。
また、tupleの要素型はすべて一致していなければならない。
Example)
make_stream::range( 1, 4 ) // { 1,2,3 }
>> flat_transformed( []( auto const& a ) { return std::make_tuple( a, a ); } ) // { 1,1,2,2,3,3 }
;
make_stream::range( 1, 4 ) // [ 1, 4 )
>> flat_transformed( []( auto const& a ) { return std::vector<std::decay_t<decltype(a)>>( a, a ); } ) // { 1,2,2,3,3,3 }
;
make_stream::range( 1, 4 ) // [ 1, 4 )
>> flat_transformed( []( auto const& a ) { return make_stream::range(0,a); } ) // { 0,0,1,0,1,2 }
;
make_stream::counter(1)
>> flat_transformed([](auto const& a) { return std::make_tuple(a, a); }) // [ 1,1,2,2,3,3,... ]
;- flat(flatten) [無限ストリーム未実装]
ストリームの要素型がレンジである場合に、レンジの要素型のストリームにフラット化します。
Example)
make_stream::generate( []{ return std::vector<int>{1,2,3}; } ) // stream<std::vector<int>
>> taken(3) // { { 1,2,3 }, { 1,2,3 }, { 1,2,3 } }
>> flatten() // stream<int>
; // { 1,2,3,1,2,3,1,2,3 }- all_flat(all_flatten) [無限ストリーム未実装]
ストリーム要素型の多重レンジコンテナを完全にフラット化します。
Example)
std::vector<std::vector<int>> aa = {
{1,2,3},
{1,2,3},
{1,2,3}
};
make_stream::of( { aa, aa } ) // stream<std::vector<std::vector<int>>>
>> all_faltten() // stream<int>
; // { 1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3 }- merged
ソート済みストリームとソート済みストリーム(レンジ)をマージする。 ソート済みかどうかのチェックなど一切行わない。
無限ストリームと有限ストリーム(レンジ)をマージすることができる。 その場合、結果が無限ストリームになる。
Example)
// 有限ストリーム+有限ストリーム
make_stream::range( 1, 3 )
.merge(
make_stream::range( 1, 3 )
)
;
// 有限ストリーム+無限ストリーム
make_stream::range( 1, 5 )
>> merged(
make_stream::counter( 1 )
)
;
// 無限ストリーム+レンジ
make_stream::counter( 1 )
>> merged(
std::vector<int>{1,2,3,4,5}
)
;
- concat
ストリームの結合。
-
peeked
-
replaced
-
replaced_if
-
distinctly
-
uniquely
-
invoked
レンジを前提とした処理で有限ストリームに適用できる。
シャッフル、集合演算、ソートなど、10種類。
終端処理が呼ばれると、遅延されていたすべての中間処理が評価されたあと、 終端処理が評価される。
出力、グループ化、コンテナへの変換、集計、条件判定など23種類。