如何将函数静态应用于非类型模板包的各个元素并对结果求和
How to statically apply a function to individual elements of a non-type template pack and sum the results?
有没有更好的方法更紧凑地在编译时实现下面的nBits的计算?请注意,问题不在于如何实施n_active_bits,我知道该怎么做。
constexpr int n_active_bits(int m) { /* count the bits */ }
template <uint8_t...Masks>
struct MaskPack
{
// is there a more concise way than to implement
//the auxiliary recursive function count_bits?
static constexpr uint8_t nBits = count_bits(Masks...);
private:
template <typename M, typename...Ms>
static constexpr uint8_t count_bits(M&& m, Ms&&...ms)
{
return n_active_bits(m) + count_bits(ms...);
}
static constexpr uint8_t count_bits()
{
return 0;
}
};
我尝试使用单行C++17折,但没有运气:
static constexpr uint8_t nBits = (n_active_bits(Masks) + ...);
使用折叠,您可以按如下方式进行操作:
template <uint8_t...Masks>
struct MaskPack {
static constexpr uint8_t nBits = (n_active_bits(Masks) + ...);
};
现场演示
请注意,n_active_bits
必须constexpr
:
constexpr int n_active_bits(unsigned int mask) {
return mask == 0 ? 0 : (mask & 0x01) + n_active_bits(mask >> 1);
}
它需要一些样板。
template<size_t I, class Indexes>
struct offset_indexes;
template<size_t I, class Indexes>
using offset_indexes_t = typename offset_indexes<I,Indexes>::type;
template<size_t I, size_t...Is>
struct offset_indexes<I, std::index_sequence<Is...>> {
using type=std::index_sequence<(I+Is)...>;
};
然后是二进制折叠:
template<size_t...Is, class Tuple>
constexpr auto retuple( std::index_sequence<Is...>, Tuple&& tuple ) {
return std::forward_as_tuple( std::get<Is>(std::forward<Tuple>(tuple))... );
}
template<class F, class T>
constexpr T binary_fold( F&& f, std::tuple<T>&& tuple ) {
return std::get<0>(std::move(tuple));
}
template<class Tuple>
struct first_element {};
template<class Tuple>
using first_element_t=typename first_element<Tuple>::type;
template<template<class...>class Z, class T0, class...Ts>
struct first_element<Z<T0,Ts...>>{using type=T0;};
template<class F, class Tuple, class E=first_element_t<std::decay_t<Tuple>>>
constexpr std::decay_t<E> binary_fold( F&& f, Tuple&& tuple ) {
constexpr auto count = std::tuple_size<std::decay_t<Tuple>>{};
using first_half = std::make_index_sequence< count/2 >;
using second_half = offset_indexes_t<
count/2,
std::make_index_sequence< (count+1)/2 >
>;
return f(
binary_fold( f, retuple( first_half{}, std::forward<Tuple>(tuple) ) ),
binary_fold( f, retuple( second_half{}, std::forward<Tuple>(tuple) ) )
);
}
它应该对binary_fold
进行递归调用的二叉树。
所有这些都使count_bits
变得容易:
template <class...Ms>
constexpr size_t count_bits(Ms&&...ms)
{
return binary_fold(
std::plus<>{},
std::make_tuple(n_active_bits(std::forward<Ms>(ms))...)
);
}
但是请注意,有很多样板文件。
我做了一个更复杂的二进制折叠,因为左/右折叠具有很深的递归深度。
活生生的例子。
相关文章:
- 如何对多维 std::vector 的所有元素求和?
- 使用 C++17 或更高版本对向量中的元素对求和的最'functional'方法?
- 在 MPI 中逐个元素对数组元素求和和收集
- 以C++递归方式对链表中的元素求和
- CUDA:所有矢量元素的级联求和
- 将彼此平行的两个 int 向量的元素求和
- 使用变换和加 () 对向量的元素进行求和和模 10^9+7<int>。有什么办法可以做到这一点吗?
- 用以下方法对数组中的元素求和的有效方法是什么
- 难以对 2D 矢量的元素求和
- 循环访问 CUDA 中的三维数组以对它们的元素求和
- 如何将函数静态应用于非类型模板包的各个元素并对结果求和
- 我如何确定我是否可以将数组中的某些元素求和为 K
- 在C++中使用do-while循环对向量的元素求和
- 在c++中对最小数组元素求和
- 递归算法对数组中值小于x的每个元素求和
- 如何使用本函数对两个字符数组进行元素相乘,并将相乘结果求和为int
- 如何对一个公共矩阵中的所有元素求和
- 通过迭代器对map的元素求和
- 如何在c++中对multimap中具有相同键的所有元素求和
- 在一个数组中查找求和为k的两个元素