namespace std {
template <class F, class... Args>
constexpr unspecified bind_back(F&&, Args&&...);
}
概要
関数の引数を末尾から順に部分適用する。
先頭から適用する場合はbind_front
を用いる。
テンプレートパラメータ制約
decay_t<F>
を適用した型をFD
、
std::decay_t<Args>...
を適用した型パラメータパックをBoundArgs
であるとして、
FD
がstd::move_constructible
要件を満たすことBoundArgs
のそれぞれの型Ti
がオブジェクト型である場合、std::move_constructible
要件を満たすこと
適格要件
conjunction_v<is_constructible<FD, F>, is_move_constructible<FD>, is_constructible<BoundArgs, Args>..., is_move_constructible<BoundArgs>...>
がtrue
であること
戻り値
呼び出し可能なf
をstd::invoke()
で呼び出した時に必要な引数列に後方一致するf
とargs...
を完全転送して保持し、後から残りの引数リストを渡すことでf
を呼び出せる未規定の関数オブジェクトを返す。
返される関数オブジェクトは渡された引数(f, args...
)を参照として保持せず、適切にコピー/ムーブして保持する。
例外
- 関数オブジェクト
f
のムーブによって任意の例外が送出される可能性がある
この機能が必要になった背景・経緯
C++23でRangeアダプタのユーザー定義がサポートされた。
Rangeアダプタオブジェクトであるadaptor
が2つ以上の引数をとる場合、以下の3つの式は等しい。
ここで、Rangeアダプタオブジェクトの第2引数以降を部分適用した結果がRangeアダプタクロージャオブジェクトとなる。
ユーザー定義するRangeアダプタオブジェクトのoperator()
において、この部分適用を行うためのユーティリティとしてbind_back
が提案された。
例
#include <ranges>
#include <vector>
#include <functional>
#include <print>
template <typename F>
class closure_t : public std::ranges::range_adaptor_closure<closure_t<F>> {
F f;
public:
constexpr closure_t(F f) : f(f) { }
template <std::ranges::range R>
requires std::invocable<F const&, R>
constexpr auto operator()(R&& r) const {
return f(std::views::all(std::forward<R>(r)));
}
};
template <typename F>
class adaptor_t {
F f;
public:
constexpr adaptor_t(F f) : f(f) { }
template <typename... Args>
constexpr auto operator()(Args&&... args) const {
if constexpr (std::invocable<F const&, Args...>) {
return f(std::forward<Args>(args)...);
} else {
return closure_t(std::bind_back(f, std::forward<Args>(args)...));
}
}
};
inline constexpr closure_t user_defined_join
= []<std::ranges::viewable_range R>
(R&& r) {
return std::ranges::join_view(std::forward<R>(r));
};
inline constexpr adaptor_t user_defined_transform
= []<std::ranges::viewable_range R, typename F>
(R&& r, F&& f) {
return std::ranges::transform_view(std::forward<R>(r), std::forward<F>(f));
};
int main() {
std::vector<std::vector<int>> vv = {{0, 1, 2}, {3, 4, 5}, {6}};
std::println("{}", vv | user_defined_join | user_defined_transform([](int x){ return x * x; }));
}
出力
[0, 1, 4, 9, 16, 25, 36]
バージョン
言語
- C++23
処理系
- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??