C++14 以降
template<class=void, std::size_t...Is>
auto indexer( std::index_sequence<Is...> ) {
return [](auto&&f){
return f( std::integral_constant<std::size_t, Is>{}... );
};
}
template<std::size_t N>
auto indexer() {
return indexer( std::make_index_sequence<N>{} );
}
template<class F>
auto fmap_over_tuple( F&& f ) {
return [f=std::forward<F>(f)](auto&& tuple) {
using Tuple = decltype(tuple);
using Tuple_d = std::decay_t<Tuple>;
auto index = indexer< std::tuple_size< Tuple_d >::value >();
return index(
[&f, &tuple](auto&&...Is) {
using std::get;
return std::make_tuple(
f( get<Is>( std::forward<Tuple>(tuple) ) )...
);
}
);
};
}
関数オブジェクトをfmap_over_tuple
取ります。タプルライクが渡されると、タプルライクの各要素で関数オブジェクトを呼び出し、そこからタプルを生成する関数オブジェクトを返します。
次に、逆参照タプルを書きます。
auto dereference_tuple = fmap_over_tuple(
[](auto&& e) { return *e; }
);
C++17 では、次のようにします。
auto[Min, Max] = dereference_tuple( std::minmax_element(lhs.begin(), lhs.end() );
そしてボブはあなたのおじです。
C++11 では、あなたがしたことをするだけです。十分にきれいにします。
C++14 のライブ例。