Rokiのチラ裏

学生による学習のログ

tuple展開も容易になった時代

スライドを作っていて色々と文書を漁って、今頃気付いた。
apply() call a function with arguments from a tuple (V3)
いつの間にこんな文書が...二年以上も前じゃないか。

#include<experimental/tuple>
#include<string>
#include<functional>

inline void f(int,float,std::string&&){}

int main()
{
    struct X{void f(int,float,std::string&&){}};

    std::experimental::apply(f,std::make_tuple(42,42.0f,"hoge"));
    std::experimental::apply([](int,float,std::string&&){},std::make_tuple(42,42.0f,"hoge"));    
    std::experimental::apply(std::mem_fn(&X::f),std::make_tuple(X(),42,42.0f,"hoge"));
}

しかも確認すれば、関数オブジェクトも渡せるじゃないか。素晴らしい。
まさか標準化されていたとは、思ってもいなかった。
それに気づかず、left arrow operator(<-)を引数付きのメンバ関数にも対応してみた - Rokiのチラ裏のエントリでは、applyを自作してしまった。車輪の再発明以外の何物でもない。
std::applyを用いて上記エントリの内容を実装すると、以下のようになる。

#include<map>
#include<experimental/tuple>

template<class _Tp>
struct larrow{
    larrow(_Tp* a_):a(a_){}
    _Tp* a;
};

template<class _Tp,class R>
constexpr R operator<(R (R::* f)(),larrow<_Tp> it)
{
    return (it.a->*f)();
}
template<class _Tp,class R>
constexpr R operator<(R (R::* f)()const,larrow<_Tp> it)
{
    return (it.a->*f)();
}
template<class _Tp,class R,class... FuncArgs,class... Tuple_Args>
R operator<(std::pair<R (_Tp::*)(FuncArgs...),std::tuple<Tuple_Args...>> pr,larrow<_Tp> it)
{
    return std::experimental::apply(pr.first,std::tuple_cat(std::make_tuple(it.a),pr.second));
}

template<class _Tp>
larrow<_Tp> operator-(_Tp& a){return larrow<_Tp>(&a);}

非常に短く済む。C++は、本当に便利な時代になったものだ。