用于获取多个容器引用的可变参数模板

时间:2019-02-14 09:24:58

标签: c++ c++11 containers variadic-templates

我想要一个函数,该函数对容器有多个引用,并返回所有元素的按元素组合。由于此操作是在非常热的循环中执行的,因此我希望能够静态地展开尽可能多的操作,而无需编写5个基本相同的函数实例。

我正在执行的算法基本上表现为

const auto result = s0 + a1 * s1 + a2 * s2 + ...

所有si是包含所有相同数量元素的容器。要累加的元素数量在编译时已知。

我正在寻找的功能应该表现为:(假设)

inline Container sum(const Container& s0, double a1, const Container& s2, ....){
    auto result = Container(s0);
    for (int i = 0; i < result.size(); ++i)
        result[i] += a1 * s1[i] + a2 * s2[i] + ...;
    return result;
}

出于性能原因,不希望编写带有运行时边界检查的某些内部循环。同样,在尝试使用运行时边界时,我遇到了无法轻松传递可变数量的函数引用的问题,在这种情况下,我应该只使用指针。

所有代码都必须是有效的C ++ 11,在此项目中,我无法使用更现代的编译器。

1 个答案:

答案 0 :(得分:2)

我将doublecontainer分组以简化代码至:

template <typename C, typename ... Cs>
C sum(const C& c0, const Cs&... cs)
{
    auto result = c0;
    for (int i = 0; i < result.size(); ++i)
#if 0 // C++17
        result[i] += (cs[i] + ...); 
#else // C++11/C++14
        const int dummy[] = {0, (static_cast<void>(result[i] += cs[i]), 0)...};
        static_cast<void>(dummy); // avoid warning for unused variable.
#endif
    return result;
}

因此,对于分组,类似:

template <typename C>
struct MulContainer
{
    auto operator [](int i) const { return d * c[i]; }

    double d;
    const C& c;
};

所以打电话,而不是

sum(c0, a1, c1, a2, c2);

您将拥有:

sum(c0, MulContainer{a1, c1}, MulContainer{a2, c2});

如果确实需要,使用std::index_sequence,您可能仍具有首次调用语法。

template <typename C, std::size_t... Is, typename Tuple>
C sum_impl(const C& c0, std::index_sequence<Is...>, const Tuple& t)
{
    return sum(c0, MulContainer{std::get<2 * Is>(t), std::get<2 * Is + 1>(t)}...);
}

template <typename C, typename ... Ts>
C final_sum(const C& c0, const Ts&... ts)
{
    static_assert(sizeof...(Ts) % 2 == 0);
    return sum_impl(c0, std::make_index_sequence<sizeof...(Ts) / 2>{}, std::tie(ts...));
}

std::index_sequence是C ++ 14,但可以在C ++ 11中实现。