C++ の std::tuple で動的にループする

たまに C++ を書かないと忘れるので…。

[コード]

#include <tuple>
#include <iostream>
#include <string>

template<typename F, typename T, std::size_t I>
void
apply_impl(F f, T const& t){
    f(std::get<I>(t));
}

template<typename F, typename T, std::size_t ...Indices>
void
apply_impl(F f, T const& t, std::size_t n, std::index_sequence<Indices...>){
    ((void (*[sizeof...(Indices)])(F, T const&)){apply_impl<F, T, Indices>...})[n](f, t);
}


template<typename F, typename ...Args>
void apply(F f, std::tuple<Args...> const& t, std::size_t n){
    apply_impl(f, t, n, std::index_sequence_for<Args...>());
}

template<typename F, typename ...Args>
void for_each(std::tuple<Args...> const& t, F f){
    for(std::size_t i = 0 ; i < sizeof...(Args) ; ++i){
        apply(f, t, i);
    }
}


int
main(){
    using namespace std::literals;
    auto data = std::tuple(1, 3.14, "homu"s);

    auto print = [](auto it){
        std::cout << it << std::endl;
    };
    apply(print, data, 0);
    apply(print, data, 1);
    apply(print, data, 2);

    for_each(data, [](auto it){
        std::cout << it + it << std::endl;
    });

    return 0;
}

[出力]

1
3.14
homu
2
6.28
homuhomu

参考にしたコードはこのあたり
動的に要素にはアクセスしているけど、値を返すことは出来ないので多相ラムダを渡して、それに値を渡すようにしています。
まー、実際 for_each だけなら std::apply とか使ったほうがよさそう。

#include <tuple>
#include <iostream>
#include <string>


template<typename F, typename ...Args>
void for_each(std::tuple<Args...> const& t, F f){
    std::apply([&](auto... args) constexpr{
        (f(args), ...);
    }, t);
}


int
main(){
    using namespace std::literals;
    auto data = std::tuple(1, 3.14, "homu"s);

    for_each(data, [](auto it){
        std::cout << it + it << std::endl;
    });

    return 0;
}
/*
2
6.28
homuhomu
*/

C++ たのしー