【问题标题】:Polynomial Multiplication using std::tuple using templates使用模板的 std::tuple 多项式乘法
【发布时间】:2023-04-05 08:18:01
【问题描述】:

假设我有 2 个表示两个多项式系数的元组,我该如何计算乘法系数。 我想使用模板来完成这个。

mul_scalar() 将元组的值与标量相乘。 我正在尝试使用此函数扩展到多项式情况。通过迭代一个元组并使用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);
}

【问题讨论】:

  • 严格来说 C++11 或 C++14/C++17 可以吗?
  • 更喜欢 C++11。但是,如果您也能告诉我其他方法,那就太好了。
  • 通过不同的方法示例改进了答案;希望这会有所帮助。

标签: c++ c++11 templates variadic-templates template-meta-programming


【解决方案1】:

递归调用很简单

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); }

你也可以用几个std::apply()mul_poly(),而不用调用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); }

【讨论】:

  • 在 C++17 中,我会使用 std::apply 而不是 std::index_sequence 来避免辅助函数样板。像这样:wandbox.org/permlink/X05YxHt1IdXN4iYq
  • @max66 实际上我将它用于不同的目的。但我认为用这个例子来解释问题会更容易。
  • @liliscent - 我仍然不习惯std::apply(),但你是对的:更简单。谢谢。
  • @CodeCollector - 根据 liliscent 的建议,我简化了很多 mul_scalar()mul_poly()
  • @liliscent - 嗨,你能解释一下这部分吗? (f(tup_e),...); - f(tup_e) 之后的逗号在这里有什么帮助?第一次看到这个
猜你喜欢
  • 2012-01-06
  • 1970-01-01
  • 1970-01-01
  • 2016-03-15
  • 2015-12-14
  • 1970-01-01
  • 1970-01-01
  • 2012-12-11
  • 1970-01-01
相关资源
最近更新 更多