diff --git a/include/xtensor/utils/xutils.hpp b/include/xtensor/utils/xutils.hpp index 8f40b0c05..8c4e0c14e 100644 --- a/include/xtensor/utils/xutils.hpp +++ b/include/xtensor/utils/xutils.hpp @@ -219,28 +219,27 @@ namespace xt namespace detail { - template - inline std::enable_if_t - accumulate_impl(F&& /*f*/, R init, const std::tuple& /*t*/) noexcept + template + R accumulate_impl(F&& f, R init, const std::tuple& t, std::index_sequence /*I*/) noexcept( + (noexcept(f(init, std::get(t))) && ...) + ) { - return init; - } - - template - inline std::enable_if_t < I - accumulate_impl(F&& f, R init, const std::tuple& t) noexcept(noexcept(f(init, std::get(t)))) - { - R res = f(init, std::get(t)); - return accumulate_impl(std::forward(f), res, t); + R res = init; + auto wrapper = [&](const auto& i, const auto& j) + { + res = f(i, j); + }; + (wrapper(res, std::get(t)), ...); + return res; } } template inline R accumulate(F&& f, R init, const std::tuple& t) noexcept( - noexcept(detail::accumulate_impl<0, F, R, T...>(std::forward(f), init, t)) + noexcept(detail::accumulate_impl(std::forward(f), init, t, std::make_index_sequence{})) ) { - return detail::accumulate_impl<0, F, R, T...>(std::forward(f), init, t); + return detail::accumulate_impl(std::forward(f), init, t, std::make_index_sequence{}); } /// @endcond diff --git a/test/test_xutils.cpp b/test/test_xutils.cpp index 5a88baa39..62df3144e 100644 --- a/test/test_xutils.cpp +++ b/test/test_xutils.cpp @@ -84,6 +84,9 @@ namespace xt }; EXPECT_EQ(8, accumulate(func_ne, 0, t)); EXPECT_TRUE(noexcept(accumulate(func_ne, 0, t))); + + const std::tuple<> t_empty{}; + EXPECT_EQ(8, accumulate(func_ne, 8, t_empty)); } template