GeezerVison is showing cpprefjp.github.io — std::ranges::fold_right - cpprefjp C++日本語リファレンス
最終更新日時:
2026年07月22日 16時08分23秒 (JST)
rotarymars
が更新
履歴
編集
function template
<algorithm>
std::ranges:: fold_right (C++23)
namespace std :: ranges {
template < bidirectional_iterator I ,
sentinel_for < I > S ,
class T ,
indirectly - binary - right - foldable < T , I > F >
constexpr auto
fold_right ( I first ,
S last ,
T init ,
F f ); // (1) C++23
template < bidirectional_iterator I ,
sentinel_for < I > S ,
class T = iter_value_t < I > ,
indirectly - binary - right - foldable < T , I > F >
constexpr auto
fold_right ( I first ,
S last ,
T init ,
F f ); // (1) C++26
template < bidirectional_range R ,
class T ,
indirectly - binary - right - foldable < T , iterator_t < R >> F >
constexpr auto
fold_right ( R && r ,
T init ,
F f ); // (2) C++23
template < bidirectional_range R ,
class T = range_value_t < R > ,
indirectly - binary - right - foldable < T , iterator_t < R >> F >
constexpr auto
fold_right ( R && r ,
T init ,
F f ); // (2) C++26
}
概要
初期値から始めて、入力範囲の各要素に対して指定された二項演算を適用していきその結果を返す。二項演算が適用される各ステップでは、前のステップまでの積算値が一緒に渡される。
この関数は、初期値を入力範囲の末尾に付加した範囲に対してその末尾の隣り合う2要素に対して与えられた二項演算を適用し、その結果によって処理した要素を置換し、処理後の範囲に対して同様の処理を残りの要素が無くなるまで繰り返すような処理を行う。
これは、関数型言語におけるリスト操作の一般形である高階関数foldrに対応し、std::accumulate を改善したものでもある。
(1) : 入力としてイテレータ範囲をとるオーバーロード
(2) : 入力として範囲を直接とるオーバーロード
入力範囲を{1, 2, 3, 4, 5}、初期値を0、二項演算を+(std::plus<> )とした時のfold_right()の処理の様子
0 : init
[1, 2, 3, 4, 5] : rng
[1, 2, 3, 4, 5] 0
5 + 0
4 + 5
3 + 9
2 + 12
1 + 14 -> fold_right(rng, 0, +)
fold_left に対しては、入力範囲の末尾から先頭に向かって処理を進めていく点が異なる。
引数
first -- 入力範囲の先頭イテレータ
last -- 入力範囲の番兵(終端イテレータ)
r -- 入力範囲のオブジェクト
init -- 初期値
f -- 適用する二項演算
f(*first, std::move(init))のような呼び出しが可能であり、その戻り値型のオブジェクトをaccとすると
acc = f(*first, std::move(acc))のような呼び出しも可能である必要がある
テンプレートパラメータ制約
indirectly-binary-right-foldableは次のように定義される説明専用のコンセプトである
flipped<F>は二項呼び出し可能なFの引数順を入れ替える説明専用のクラステンプレートであり、次のように定義される
template < class F >
class flipped {
F f ;
public :
template < class T , class U >
requires invocable < F & , U , T >
invoke_result_t < F & , U , T > operator ()( T && , U && );
};
すなわち、二項演算Fの引数順が逆になることを除いてfold_left と同じ制約となる。
ただし、fold_rightはその処理の都合上、入力範囲に対してbidirectional_range であることを要求する(fold_leftはinput_range )。
戻り値
(1), (2)ともに、以下と等価
using U = decay_t < invoke_result_t < F & , iter_reference_t < I > , T >> ;
if ( first == last )
return U ( std :: move ( init ));
I tail = ranges :: next ( first , last );
U accum = invoke ( f , *-- tail , std :: move ( init ));
while ( first != tail )
accum = invoke ( f , *-- tail , std :: move ( accum ));
return accum ;
空の入力範囲に対しては初期値initを返す。
計算量
入力範囲r([first, last))の要素数をNとすると、正確にN回のfの適用が行われる。
備考
例
基本的な数値集計処理の例
出力
55
1.125
処理順序を表示する例
#include <ranges>
#include <algorithm>
#include <functional>
#include <format>
#include <vector>
#include <print>
#include <concepts>
#include <string>
#include <utility>
using namespace std :: ranges ;
int main () {
// [a, b, c, d, e, f]
range auto rng = views :: iota ( 'a' , 'g' );
const std::string init = "init" ;
// fold_left の二項演算op
auto op_left = []( std::string acc , char elem ) {
acc += " -> " ;
acc += elem ;
return acc ;
};
// fold_right の二項演算op
auto op_right = [ op_left ]( char elem , std::string acc ) {
return op_left ( std :: move ( acc ), elem );
};
auto resl = fold_left ( rng , init , op_left );
auto resr = fold_right ( rng , init , op_right );
std::println ( "{:s}" , resl );
std::println ( "{:s}" , resr );
}
出力
init -> a -> b -> c -> d -> e -> f
init -> f -> e -> d -> c -> b -> a
入力範囲を反転させる例
出力
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
波カッコ初期化を入力として使用する (C++26)
出力
6
実装例
template < bidirectional_iterator I , sentinel_for < I > S , class T ,
indirectly - binary - right - foldable < T , I > F >
constexpr auto fold_right ( I first , S last , T init , F f ) {
using U = decay_t < invoke_result_t < F & , iter_reference_t < I > , T >> ;
if ( first == last ) {
return U ( std :: move ( init ));
}
I tail = ranges :: next ( first , last );
U accum = invoke ( f , *-- tail , std :: move ( init ));
while ( first != tail ) {
accum = invoke ( f , *-- tail , std :: move ( accum ));
}
return accum ; // 暗黙ムーブ or NRVO
}
バージョン
言語
処理系
関連項目
参照