如何在 C++ 中设计一个矩阵

huangapple go评论99阅读模式
英文:

How to design a matrix in C++

问题

以下是翻译的代码部分:

  1. 我想设计一个矩阵,并希望不能初始化它不当。例如,考虑以下情况:
  2. template <typename T, unsigned int R, unsigned int C>
  3. class matrix {
  4. std::array<T, R*C> _data;
  5. //... 构造函数等 ...
  6. };
  7. 现在,我想要一个设计,其中以下操作是可能的,甚至不可能的:
  8. auto mat1 = matrix<int, 2, 2>{1, 2, 3, 4};
  9. auto mat2 = matrix<int, 2, 2>{1, 2, 3, 4, 5}; // 错误!希望在编译时发生错误
  10. auto mat3 = matrix{1, 2, 3, 4}; // matrix<int, 2, 2>;
  11. 是否有一种优雅的方式来表达这一点?使用构造函数和初始化列表吗?是否可以检查所提供的参数的大小?
英文:

I wanted to design a matrix and wanted that it is not possible to initialize it bad. Consider for example this:

  1. template &lt;typename T, unsigned int R, unsigned int C&gt;
  2. class matrix {
  3. array&lt;T,R*C&gt; _data;
  4. //... Constructors, etc. ...
  5. };

Now I would like to have a design where the following is possible or even not:

  1. auto mat1 = matrix&lt;int,2,2&gt;{1, 2, 3, 4};
  2. auto mat2 = matrix&lt;int,2,2&gt;{1, 2, 3, 4, 5}; // Error! Hopefully at compile time
  3. auto mat3 = matrix{1,2,3,4}; // matrix&lt;int,2,2&gt;

Is there a elegant way to express that? With Constructors and initializer_list? Is it possible to check the size of provided arguments?

答案1

得分: 3

你可以添加一个接受任意数量参数的构造函数 + 一个推导指南来计算大小:

  1. template<class T, std::size_t R, std::size_t C>
  2. struct matrix {
  3. // 接受任意类型并进行转发:
  4. template<class... Args>
  5. matrix(Args&&... args) : _data{std::forward<Args>(args)...} {
  6. // 断言大小是否正确:
  7. static_assert(sizeof...(Args) == R * C, "初始化无效");
  8. }
  9. std::array<T, R * C> _data;
  10. };
  11. // 整数平方根
  12. template<std::size_t T, std::size_t N = 0>
  13. constexpr std::size_t isqrt() {
  14. if constexpr ((N+1) * (N+1) <= T) return isqrt<T, N + 1>();
  15. return N;
  16. }
  17. // 推导指南:
  18. template<class T, class... Args>
  19. matrix(T&&, Args&&...) ->
  20. matrix<T, isqrt<sizeof...(Args) + 1>(), isqrt<sizeof...(Args) + 1>()>;

示例

英文:

You could add a constructor taking an arbitrary amount of arguments + a deduction guide to calculate the sizes:

  1. template &lt;class T, std::size_t R, std::size_t C&gt;
  2. struct matrix {
  3. // take anything and forward it:
  4. template &lt;class... Args&gt;
  5. matrix(Args&amp;&amp;... args) : _data{std::forward&lt;Args&gt;(args)...} {
  6. // assert that the sizes are correct:
  7. static_assert(sizeof...(Args) == R * C, &quot;invalid init&quot;);
  8. }
  9. std::array&lt;T, R * C&gt; _data;
  10. };
  11. // integer square root
  12. template&lt;std::size_t T, std::size_t N = 0&gt;
  13. constexpr std::size_t isqrt() {
  14. if constexpr ((N+1) * (N+1) &lt;= T) return isqrt&lt;T, N + 1&gt;();
  15. return N;
  16. }
  17. // Deduction guide:
  18. template &lt;class T, class... Args&gt;
  19. matrix(T&amp;&amp;, Args&amp;&amp;...) -&gt;
  20. matrix&lt;T, isqrt&lt;sizeof...(Args) + 1&gt;(), isqrt&lt;sizeof...(Args) + 1&gt;()&gt;;

Demo

huangapple
  • 本文由 发表于 2023年2月8日 23:12:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/75387810.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定