ノート 7/24
std::transformは処理を適用・結果を格納するコンテナの範囲をイテレータとして受け取る関数だが、一々
std::vector<int> w(v.size()); std::transform(v.begin(), v.end(), w.begin(), w.end(), f);
と書くのが面倒な上、二行も使う。 そこで、コンテナvの参照と関数fから上記の処理をしてwを返すようなラッパが欲しい。
テンプレートテンプレート
クラステンプレート(名前だけでは不完全な型)をテンプレートで表すにはテンプレートテンプレートを使う。
template <class T> sturct A { T t; }; //Tとしてstruct Aを指定できる template <template <class> class T> struct B { T<double> t; };
実引数からクラステンプレートを推論させる
template <template <class> class T, class U> void f(T<U>);
- 上記の関数fに
A<int>{}
を与えた場合、T=A, U=intと判断される。
実装する
template < template <class...> class C class... Args, class F, class R = typename std::invoke_result_t<F&, typename C<Args...>::value_type const&> > auto transform(C<Args...> const& t, F&& f) { //Args...の中でR以外のパラメータは省略可能と仮定する auto u = C<R>(t.size()); std::transform(t.begin(), t.end(), u.begin(), f); return u; }
template <class...> class C
は任意のコンテナを表すことができる- Args...はCのテンプレート引数
- Fはファンクタ
- RはFをCの要素に適用して返ってくる値の型
- transform関数の第一引数では上で述べた推論を利用している。例えば
std::vector<int, std::allocator<int>>{}
を与えればC=std::vector, Args...=int, std::allocator<int>
になる。
欠点
- std::mapは引数に
std::pair<S, T>
を取らないためC<R>
の実体化に失敗してコンパイルエラー.何か工夫が必要