什么是通用化模板以将可变数量的参数(作为模板参数给出的计数)传递给函数的干净方法?例如函数
permute
,如下:
template<std::size_t N>
using byte_vector_t = uint8_t __attribute__((ext_vector_type(N)));
template <std::size_t N, int(*f)(int)>
byte_vector_t<N> permute(byte_vector_t<N> x, byte_vector_t<N> y) {
return __builtin_shufflevector(x, y, f(0), f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13), f(14), f(15) );
}
template <std::size_t N>
byte_vector_t<N> zip_lo(byte_vector_t<N> x, byte_vector_t<N> y) {
auto f = [](int i) -> int { return ((i & 1) ? N : 0) + (i / 2); };
return permute<N, f>(x, y);
}
但这仅适用于 N=16:
// works
typedef uint8_t test16_t __attribute__((ext_vector_type(16)));
test16_t zip_lo16(test16_t x, test16_t y) {
return zip_lo(x, y);
}
// does not work
typedef uint8_t test8_t __attribute__((ext_vector_type(8)));
test8_t zip_lo8(test8_t& x, test8_t& y) {
return zip_lo(x, y);
}
std::apply
似乎可能相关,但 __builtin_shufflevector
拒绝传递进去。即使它有效,我仍然不知道如何最好地生成元组。
index_sequence
:
#include <utility>
template <std::size_t N, int (*f)(int)>
byte_vector_t<N> permute(byte_vector_t<N> x, byte_vector_t<N> y) {
return [&]<std::size_t... I>(std::index_sequence<I...>) {
return __builtin_shufflevector(x, y, f(I)...);
}(std::make_index_sequence<N>());
}
如果您使用 C++17,则无法使用通用 lambda,因此您需要一个辅助函数:
template <int (*f)(int), std::size_t... I>
byte_vector_t<sizeof...(I)> permute_helper(byte_vector_t<sizeof...(I)> x,
byte_vector_t<sizeof...(I)> y,
std::index_sequence<I...>) {
return __builtin_shufflevector(x, y, f(I)...);
}
template <std::size_t N, int (*f)(int)>
byte_vector_t<N> permute(byte_vector_t<N> x, byte_vector_t<N> y) {
return permute_helper<f>(x, y, std::make_index_sequence<N>());
}