Векторное произведение нескольких векторов с использованием мета-функции

#c #c 14 #metaprogramming #template-meta-programming

Вопрос:

Учитывая вектор, подобный:

   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>

Комментарии:

1. Что делать, если у одного из vec s разное количество аргументов? например: multiVecs<vec<0,1,2>, vec<1,2,3, 4>> ?

Ответ №1:

Давайте начнем с двух векторных произведений и начнем оттуда.

 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;
 

Это отлично работает, поэтому теперь мы просто сложим его поверх пачки.

К сожалению, в C 14 нет сложенных выражений, поэтому нам приходится делать это вручную.

 template <typename...>
struct multiVecs;

template <typename... Ts>
using multiVecs_t = typename multiVecs<Ts...>::type;

template <typename result>
struct multiVecs<result> {
    using type = resu<
};

template <typename first, typename second, typename... rest>
struct multiVecs<first, second, rest...> {
    using type = multiVecs_t<multiplies<first, second>, rest...>;
};
 

Это тоже прекрасно

Комментарии:

1. Вау, красиво упакованы параметры….

Ответ №2:

Решение 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;
};
 

ДЕМОНСТРАЦИЯ.

Комментарии:

1. Немного объяснений было бы неплохо, как и другой ответ!