Полиномиальное умножение с использованием std :: tuple с использованием шаблонов - PullRequest
0 голосов
/ 16 декабря 2018

Предполагая, что у меня есть 2 кортежа, представляющих коэффициенты двух полиномов, как мне вычислить там коэффициенты умножения.Я хочу сделать это с помощью шаблона.

mul_scalar() умножает значение кортежа на a со скаляром.Я пытаюсь использовать эту функцию для расширения до полиномиального случая.Итерируя по одному кортежу и используя mul_scalar()

#include <tuple>
#include <utility> 
#include <iostream>

template<std::size_t I = 0, typename T, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
mul_scalar(const T& lhs, const std::tuple<Tp...> rhs ) // Unused arguments are given no names.
{ }

template<std::size_t I = 0, typename T, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
mul_scalar(const T& lhs, const std::tuple<Tp...> rhs)
{
    std::cout << (std::get<I>(rhs))*lhs << " ";
    mul_scalar<I + 1, T, Tp...>(lhs, rhs);
}

template <std::size_t I = 0, template <typename ...> class Tup1, template <typename ...> class Tup2, typename ...A, typename ...B>
inline typename std::enable_if<I < sizeof...(A), void>::type
mul_poly(const Tup1<A...>& lhs, const Tup2<B...> rhs)
{
    mul_scalar(std::get<I>(lhs), rhs);
    //mul_poly(lhs, rhs); with I = I + 1
    // However I can't figure how to give other template args
}

int main(){
    auto poly_1 = std::make_tuple(2,1);
    auto poly_2 = std::make_tuple(3,4,5);
    mul_scalar(3,poly_1);
    std::cout << "\n";

    // Expected output 6 8 10 3 4 5
    mul_poly(poly_1, poly_2);
}

1 Ответ

0 голосов
/ 16 декабря 2018

Рекурсивный вызов прост

mul_poly<I+1u>(lhs, rhs);

, но вы должны добавить наземный регистр

template <std::size_t I = 0, template <typename ...> class Tup1,
          template <typename ...> class Tup2, typename ...A, typename ...B>
inline typename std::enable_if<I == sizeof...(A), void>::type
    mul_poly (const Tup1<A...> &, const Tup2<B...> &)
 { }

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

Предложение бонуса: если вы можете использовать C ++ 17, вы можете избежать SFINAE и рекурсии, для mul_scalar(), используя std::index_sequence / std::make_index_sequence (или std::index_sequence_for) и сворачивание шаблона какследует

template <typename T, typename ... Tp, std::size_t ... Is>
void mul_scalar_helper (T const & lhs, std::tuple<Tp...> const & rhs,
                        std::index_sequence<Is...> const &)
 { ((std::cout << (std::get<Is>(rhs))*lhs << ' '), ...); }

template <typename T, typename ... Tp>
void mul_scalar (T const & lhs, std::tuple<Tp...> const & rhs)
 { mul_scalar_helper(lhs, rhs, std::index_sequence_for<Tp...>{}); }

Для mul_poly() нет большой разницы

template <template <typename ...> class Tup1,
          template <typename ...> class Tup2,
          typename ... A, typename ... B, std::size_t ... Is>
void mul_poly_helper (Tup1<A...> const & lhs, Tup2<B...> const & rhs,
                      std::index_sequence<Is...> const &)
 { (mul_scalar(std::get<Is>(lhs), rhs), ...); }

template <template <typename ...> class Tup1,
          template <typename ...> class Tup2,
          typename ...A, typename ...B>
void mul_poly (Tup1<A...> const & lhs, Tup2<B...> const & rhs)
 { mul_poly_helper(lhs, rhs, std::index_sequence_for<A...>{}); }

В любом случае ... Вы уверены, что std::tuple является правильным контейнером?Рассматривали ли вы std::array?

--- РЕДАКТИРОВАТЬ ---

Следуя совету Liliscent (спасибо!), Вы можете избежать вспомогательных функций и std::index_sequence/ std::index_sequence_for используя std::apply() просто записав

template <typename T, typename ... Tp>
void mul_scalar (T const & lhs, std::tuple<Tp...> const & rhs)
 { std::apply([&](auto const & ... x){ ((std::cout << x*lhs << ' '), ...); }, rhs); }

template <template <typename ...> class Tup1,
          template <typename ...> class Tup2,
          typename ...A, typename ...B>
void mul_poly (Tup1<A...> const & lhs, Tup2<B...> const & rhs)
 { std::apply([&](auto const & ... x){ (mul_scalar(x, rhs), ...); }, lhs); }

Вы также можете написать mul_poly() с парой std::apply(), без вызова mul_scalar()

template <template <typename ...> class Tup1,
          template <typename ...> class Tup2,
          typename ...A, typename ...B>
void mul_poly (Tup1<A...> const & lhs, Tup2<B...> const & rhs)
 { std::apply([&](auto const & ... x){
      (std::apply([x](auto const & ... y){ ((std::cout << x*y << ' '), ...); }, 
                  rhs), ...); }, lhs); }
...