I\'ve got a custom class that has a tuple-like interface. Because I want my code to be as generic as possible, I thought that it would be a good idea to base my algorithms o
With C++1z it's pretty simple with fold expressions. First, forward the tuple to an _impl
function and provide it with index sequence to access all tuple elements, then sum:
template
auto sum_components_impl(T const& t, std::index_sequence)
{
return (std::get(t) + ...);
}
template
int sum_components(const Tuple& t)
{
constexpr auto size = std::tuple_size{};
return sum_components_impl(t, std::make_index_sequence{});
}
demo
A C++14 approach would be to recursively sum a variadic pack:
int sum()
{
return 0;
}
template
auto sum(T&& t, Us&&... us)
{
return std::forward(t) + sum(std::forward(us)...);
}
template
auto sum_components_impl(T const& t, std::index_sequence)
{
return sum(std::get(t)...);
}
template
int sum_components(const Tuple& t)
{
constexpr auto size = std::tuple_size{};
return sum_components_impl(t, std::make_index_sequence{});
}
demo
A C++11 approach would be the C++14 approach with custom implementation of index_sequence
. For example from here.
As @ildjarn pointed out in the comments, the above examples are both employing right folds, while many programmers expect left folds in their code. The C++1z version is trivially changeable:
template
auto sum_components_impl(T const& t, std::index_sequence)
{
return (... + std::get(t));
}
demo
And the C++14 isn't much worse, but there are more changes:
template
auto sum(T&& t, Us&&... us)
{
return sum(std::forward(us)...) + std::forward(t);
}
template
auto sum_components_impl(T const& t, std::index_sequence)
{
constexpr auto last_index = sizeof...(Is) - 1;
return sum(std::get(t)...);
}
demo