使用C++1z和fold expressions非常简单。首先,将元组转发到一个_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的方法是使用自定义实现的index_sequence
的C++14方法。例如从这里。
正如@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)...);
}
演示
decltype(auto)
的运用。 - T.C.T&&
中间结果可能会与上述内容发生冲突。但现在我认为这是表达式模板的问题。 - Yakk - Adam Nevraumontstd::apply
,而我以前不知道。我接受了您的解决方案。 - Max