使用元函数的多个向量的向量积
Vector product of multiple vectors using meta function
给定一个向量:
template<int... elements>
struct vec;
如何创建一个元函数,它可以逐个元素地乘以所有提供的向量。例如
template<typename ...AllVecs>
struct multiVecs
{
using type = ....
}
其中类型将逐个元素地执行所有产品。例如给定三个向量:
multiVecs< vec<0,1,2>, vec<1,2,3>, vec<2,3,4> >
我应该得到一个 vec<0*1*2, 1*2*3, 2*3*4>
C++17 解决方案:
template<int... Elements>
struct vec;
template<int Element, class... Vec>
struct vec_impl { };
template<class Vec>
struct to_vec_impl;
template<int First, int... Rest>
struct to_vec_impl<vec<First, Rest...>> {
using type = vec_impl<First, vec<Rest...>>;
};
template<>
struct to_vec_impl<vec<>> {
using type = vec_impl<-1>;
};
template<class Result_vec, class... Vecs>
struct gen_vec_impl;
template<int... Products, template<int, class...> class... VecImpls,
int... First, class... Vecs>
struct gen_vec_impl<vec<Products...>, VecImpls<First, Vecs>...>
: gen_vec_impl<vec<Products..., (First * ... * 1)>,
typename to_vec_impl<Vecs>::type...>
{ };
template<int... Products, template<int, class...> class... VecImpls>
struct gen_vec_impl<vec<Products...>, VecImpls<-1>...> {
using type = vec<Products...>;
};
template<class... AllVecs>
struct multiVecs {
using type = typename gen_vec_impl<
vec<>, typename to_vec_impl<AllVecs>::type...>::type;
};
让我们从两个向量积开始,然后从那里开始。
template <typename lhs, typename rhs>
struct multiplies;
template <int... lhs, int... rhs>
struct multiplies<vec<lhs...>, vec<rhs...>> {
static_assert(sizeof...(lhs) == sizeof...(rhs), "Vector arity mismatch");
using type = vec<(lhs * rhs)...>
};
template <typename lhs, typename rhs>
using multiplies_t = typename multiplies<lhs, rhs>::type;
This works fine,所以现在我们把它折叠起来。
不幸的是,C++14 没有折叠表达式,所以我们必须手写。
template <typename...>
struct multiVecs;
template <typename... Ts>
using multiVecs_t = typename multiVecs<Ts...>::type;
template <typename result>
struct multiVecs<result> {
using type = result;
};
template <typename first, typename second, typename... rest>
struct multiVecs<first, second, rest...> {
using type = multiVecs_t<multiplies<first, second>, rest...>;
};
给定一个向量:
template<int... elements>
struct vec;
如何创建一个元函数,它可以逐个元素地乘以所有提供的向量。例如
template<typename ...AllVecs>
struct multiVecs
{
using type = ....
}
其中类型将逐个元素地执行所有产品。例如给定三个向量:
multiVecs< vec<0,1,2>, vec<1,2,3>, vec<2,3,4> >
我应该得到一个 vec<0*1*2, 1*2*3, 2*3*4>
C++17 解决方案:
template<int... Elements>
struct vec;
template<int Element, class... Vec>
struct vec_impl { };
template<class Vec>
struct to_vec_impl;
template<int First, int... Rest>
struct to_vec_impl<vec<First, Rest...>> {
using type = vec_impl<First, vec<Rest...>>;
};
template<>
struct to_vec_impl<vec<>> {
using type = vec_impl<-1>;
};
template<class Result_vec, class... Vecs>
struct gen_vec_impl;
template<int... Products, template<int, class...> class... VecImpls,
int... First, class... Vecs>
struct gen_vec_impl<vec<Products...>, VecImpls<First, Vecs>...>
: gen_vec_impl<vec<Products..., (First * ... * 1)>,
typename to_vec_impl<Vecs>::type...>
{ };
template<int... Products, template<int, class...> class... VecImpls>
struct gen_vec_impl<vec<Products...>, VecImpls<-1>...> {
using type = vec<Products...>;
};
template<class... AllVecs>
struct multiVecs {
using type = typename gen_vec_impl<
vec<>, typename to_vec_impl<AllVecs>::type...>::type;
};
让我们从两个向量积开始,然后从那里开始。
template <typename lhs, typename rhs>
struct multiplies;
template <int... lhs, int... rhs>
struct multiplies<vec<lhs...>, vec<rhs...>> {
static_assert(sizeof...(lhs) == sizeof...(rhs), "Vector arity mismatch");
using type = vec<(lhs * rhs)...>
};
template <typename lhs, typename rhs>
using multiplies_t = typename multiplies<lhs, rhs>::type;
This works fine,所以现在我们把它折叠起来。
不幸的是,C++14 没有折叠表达式,所以我们必须手写。
template <typename...>
struct multiVecs;
template <typename... Ts>
using multiVecs_t = typename multiVecs<Ts...>::type;
template <typename result>
struct multiVecs<result> {
using type = result;
};
template <typename first, typename second, typename... rest>
struct multiVecs<first, second, rest...> {
using type = multiVecs_t<multiplies<first, second>, rest...>;
};