C++1z では、fold 式を使用すると非常に簡単です。まず、タプルを_impl
関数に転送し、すべてのタプル要素にアクセスするためのインデックス シーケンスを提供してから、合計します。
template<typename T, size_t... Is>
auto sum_components_impl(T const& t, std::index_sequence<Is...>)
{
return (std::get<Is>(t) + ...);
}
template <class Tuple>
int sum_components(const Tuple& t)
{
constexpr auto size = std::tuple_size<Tuple>{};
return sum_components_impl(t, std::make_index_sequence<size>{});
}
デモ
C++14 のアプローチは、可変個引数パックを再帰的に合計することです。
int sum()
{
return 0;
}
template<typename T, typename... Us>
auto sum(T&& t, Us&&... us)
{
return std::forward<T>(t) + sum(std::forward<Us>(us)...);
}
template<typename T, size_t... Is>
auto sum_components_impl(T const& t, std::index_sequence<Is...>)
{
return sum(std::get<Is>(t)...);
}
template <class Tuple>
int sum_components(const Tuple& t)
{
constexpr auto size = std::tuple_size<Tuple>{};
return sum_components_impl(t, std::make_index_sequence<size>{});
}
デモ
C++11 アプローチは、カスタム実装の C++14 アプローチになりますindex_sequence
。たとえばここから。
@ildjarn がコメントで指摘したように、上記の例は両方とも右折畳みを採用していますが、多くのプログラマーはコードで左折畳みを期待しています。C++1z バージョンは簡単に変更できます。
template<typename T, size_t... Is>
auto sum_components_impl(T const& t, std::index_sequence<Is...>)
{
return (... + std::get<Is>(t));
}
デモ
C++14 もそれほど悪くはありませんが、他にも変更点があります。
template<typename T, typename... Us>
auto sum(T&& t, Us&&... us)
{
return sum(std::forward<Us>(us)...) + std::forward<T>(t);
}
template<typename T, size_t... Is>
auto sum_components_impl(T const& t, std::index_sequence<Is...>)
{
constexpr auto last_index = sizeof...(Is) - 1;
return sum(std::get<last_index - Is>(t)...);
}
デモ