From e546e19a6376dab6545ae833a7f54fb23ddef501 Mon Sep 17 00:00:00 2001 From: Drew Hubley Date: Tue, 18 Nov 2025 20:09:11 -0400 Subject: [PATCH 1/2] Updated for_each to use a fold over recurssion --- include/xtensor/utils/xutils.hpp | 51 +++++++++++--------------------- 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/include/xtensor/utils/xutils.hpp b/include/xtensor/utils/xutils.hpp index 8f40b0c05..85ef31d5d 100644 --- a/include/xtensor/utils/xutils.hpp +++ b/include/xtensor/utils/xutils.hpp @@ -163,52 +163,37 @@ namespace xt namespace detail { - template - inline typename std::enable_if::type - for_each_impl(F&& /*f*/, std::tuple& /*t*/) noexcept + template + void for_each(F&& f, std::tuple& t, std::index_sequence) noexcept( + (noexcept(f(std::get(t))) && ...) + ) { + (f(std::get(t)), ...); } - template - inline typename std::enable_if < I::type - for_each_impl(F&& f, std::tuple& t) noexcept(noexcept(f(std::get(t)))) + template + void for_each(F&& f, const std::tuple& t, std::index_sequence) noexcept( + (noexcept(f(std::get(t))) && ...) + ) { - f(std::get(t)); - for_each_impl(std::forward(f), t); + (f(std::get(t)), ...); } } - template - inline void for_each(F&& f, std::tuple& t) noexcept( - noexcept(detail::for_each_impl<0, F, T...>(std::forward(f), t)) + template + inline void for_each(F&& f, std::tuple& t) noexcept( + noexcept(detail::for_each(std::forward(f), t, std::make_index_sequence{})) ) { - detail::for_each_impl<0, F, T...>(std::forward(f), t); + detail::for_each(std::forward(f), t, std::make_index_sequence{}); } - namespace detail - { - template - inline typename std::enable_if::type - for_each_impl(F&& /*f*/, const std::tuple& /*t*/) noexcept - { - } - - template - inline typename std::enable_if < I::type - for_each_impl(F&& f, const std::tuple& t) noexcept(noexcept(f(std::get(t)))) - { - f(std::get(t)); - for_each_impl(std::forward(f), t); - } - } - - template - inline void for_each(F&& f, const std::tuple& t) noexcept( - noexcept(detail::for_each_impl<0, F, T...>(std::forward(f), t)) + template + inline void for_each(F&& f, const std::tuple& t) noexcept( + noexcept(detail::for_each(std::forward(f), t, std::make_index_sequence{})) ) { - detail::for_each_impl<0, F, T...>(std::forward(f), t); + detail::for_each(std::forward(f), t, std::make_index_sequence{}); } /***************************** From 1fb92a74df814e3df3dd0487bf75b461f2406f77 Mon Sep 17 00:00:00 2001 From: Drew Hubley Date: Tue, 18 Nov 2025 21:20:53 -0400 Subject: [PATCH 2/2] Updated accumulate to use C++17 folds rather than recursion --- include/xtensor/utils/xutils.hpp | 27 +++++++++++++-------------- test/test_xutils.cpp | 3 +++ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/include/xtensor/utils/xutils.hpp b/include/xtensor/utils/xutils.hpp index 85ef31d5d..2e97f67db 100644 --- a/include/xtensor/utils/xutils.hpp +++ b/include/xtensor/utils/xutils.hpp @@ -204,28 +204,27 @@ namespace xt namespace detail { - template - inline std::enable_if_t - accumulate_impl(F&& /*f*/, R init, const std::tuple& /*t*/) noexcept - { - 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)))) + template + R accumulate_impl(F&& f, R init, const std::tuple& t, std::index_sequence /*I*/) 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