Avec C++ 1z c'est assez simple avec fold expressions. Tout d'abord, transférer le nuplet à une fonction _impl
et lui fournit séquence d'index pour accéder à tous les éléments de tuple, puis somme:
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>{});
}
demo
Une approche 14 C++ serait de somme récursive un pack variadique:
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>{});
}
demo
Une approche C++ 11 serait l'approche C++ 14 avec une implémentation personnalisée de index_sequence
. Par exemple de here.
Comme @ildjarn a souligné dans les commentaires, les exemples ci-dessus sont tous les deux emploient des plis à droite, tandis que de nombreux programmeurs attendent plis gauche dans leur code. La version C++ 1Z est trivialement variable:
template<typename T, size_t... Is>
auto sum_components_impl(T const& t, std::index_sequence<Is...>)
{
return (... + std::get<Is>(t));
}
demo
Et le 14 C++ est pas bien pire, mais il y a plus de changements:
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)...);
}
demo
Juste besoin de saupoudrer 'decltype (auto)'. –
@ T.C. Ajouté au goût. Omis à l'origine parce que je ne voulais pas penser à des modèles d'expression et d'autres dégâts. Il y a une faible chance que les résultats intermédiaires retournés comme 'T && 'à partir d'un champ d'un objet de stockage automatique temporaire puissent rompre avec ce qui précède. Mais maintenant je pense que c'est le problème du modèle d'expression. – Yakk
Merci beaucoup. Cette solution est encore meilleure que celle de @ krzaq parce que vous utilisez 'std :: apply' que je ne connaissais pas auparavant. J'ai accepté votre solution à la place. – Max