インデックス付きtransform
jsのように添え字が欲しいことがあったので書いた。
#include <type_traits> #include <algorithm> struct result_of { template <class T, class R> struct y { using type = R; static inline constexpr bool value = T::value; }; template <class C, class F, class... Args> static auto f() -> y<std::false_type, std::invoke_result_t<F&, Args...>>; template <class C, class F, class... Args> static auto f() -> y<std::true_type, std::invoke_result_t<F&, Args..., C>>; }; template <class C, class F, class... Args> using result_of_t = decltype(result_of::f<C, F, Args...>()); //添え字を与えてくれるstd::transform template < template <class...> class C, class... Args, class F, class R = result_of_t<std::size_t, F, typename C<Args...>::value_type> > static inline auto transform(C<Args...> const& t, F&& f) { //Cはテンプレート引数を省略できるとする auto u = C<typename R::type>(t.size()); if constexpr (R::value) { std::transform(t.begin(), t.end(), u.begin(), [&f](auto const& x) { static size_t i = 0; return f(x, i++); }); } else { std::transform(t.begin(), t.end(), u.begin(), f); } return u; }
result_of_t<C, F, Args...>::value
はファンクタをArgs..., C
で呼び出せるならtrue
, そうでないときはfalse
となる。またresult_of_t<C, F, Args...>::type
はファンクタの返り値の型である。
例
#include <iostream> #include <vector> int main() { auto v = transform(std::vector{2, 4, 6, 8}, [](auto x, auto i) { std::cout << i << ":" << x * i << std::endl; return x * i; }); }
結果
0:0 1:4 2:12 3:24