改善折叠功能

问题描述 投票:0回答:1

我已经在C ++中实现了一个简单的fold函数,该函数接受一个lambda,并且可以在编译时同时折叠多个向量。我想知道是否可以以某种方式简化它(我提供了递归版本和迭代递归版本-我不确定哪个应该有更好的性能):https://godbolt.org/z/39pW81

也欢迎性能优化-在这方面,两种方法中的任何一种都更快吗?

template<int I, typename type_identity, typename type_head, int N, typename ...type_tail, int ...N_tail,  typename Function>
auto foldHelperR(Function&& func, const type_identity& id, const tvecn<type_head, N>& head, const tvecn<type_tail, N_tail>&... tail)
{
    if constexpr (I>0)
    {
        return func(foldHelperR<I-1>(std::forward<Function>(func), id, head, tail...), head[I], tail[I]...);
    }
    else
    {
        return func(id, head[0], tail[0]...);
    }
}

template<int I, typename type_identity, typename type_head, int N, typename ...type_tail, int ...N_tail,  typename Function>
auto foldHelperI(Function&& func, const type_identity id, const tvecn<type_head, N>& head, const tvecn<type_tail, N_tail>&... tail)
{
    if constexpr (I<N-1)
    {
        return foldHelperI<I+1>(std::forward<Function>(func), func(id, head[I], tail[I]...), head, tail...);
    }
    else
    {
        return func(id, head[N-1], tail[N-1]...);
    }
}

template<typename type_identity, typename type_head, int N_head, typename ...type_tail, int ...N_tail, typename Function = void (const type_identity&, const type_head&, const type_tail&...)>
constexpr auto fold(Function&& func, const type_identity& id, const tvecn<type_head, N_head>& head, const tvecn<type_tail, N_tail>&... tail)
{
    static_assert(std::is_invocable_v<Function, const type_identity&, const type_head&, const type_tail &...>,
     "The function cannot be invoked with these zip arguments (possibly wrong argument count).");
    static_assert(all_equal_v<N_head, N_tail...>, "Vector sizes must match.");

    //return foldHelperR<N_head-1>(std::forward<Function>(func), id, head, tail...);
    return foldHelperI<0>(std::forward<Function>(func), id, head, tail...);
}

int main()
{
    tvecn<int,3> a(1,2,3);
    return fold([](auto x, auto y, auto z) {return x+y+z;}, 0, a, a);
}
c++ templates c++17 variadic-templates fold
1个回答
0
投票

带有Fold表达式,可能是:

template <typename F, typename Init, std::size_t... Is, typename... Arrays>
constexpr auto fold(F&& f, Init init, std::index_sequence<Is...>, Arrays&&... arrays)
{
    auto l = [&](Init init, std::size_t i){ return f(init, arrays[i]...); };
    return ((init = l(init, Is)), ...);
}


template <typename F, typename Init, typename Array, typename ... Arrays>
constexpr auto fold(F&& f, Init init, Array&& array, Arrays&&... arrays)
{
    static_assert(((arrays.size() == array.size()) && ...));
    return fold(f, init, std::make_index_sequence<array.size()>{}, array, arrays...);
}

Demo

© www.soinside.com 2019 - 2024. All rights reserved.