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

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

How to design a matrix in C++

问题

以下是翻译的代码部分:

我想设计一个矩阵,并希望不能初始化它不当。例如,考虑以下情况:
template <typename T, unsigned int R, unsigned int C>
class matrix {
  std::array<T, R*C> _data;

  //... 构造函数等 ...
};

现在,我想要一个设计,其中以下操作是可能的,甚至不可能的:
auto mat1 = matrix<int, 2, 2>{1, 2, 3, 4};
auto mat2 = matrix<int, 2, 2>{1, 2, 3, 4, 5}; // 错误!希望在编译时发生错误
auto mat3 = matrix{1, 2, 3, 4}; // matrix<int, 2, 2>;

是否有一种优雅的方式来表达这一点?使用构造函数和初始化列表吗?是否可以检查所提供的参数的大小?
英文:

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

template &lt;typename T, unsigned int R, unsigned int C&gt;
class matrix {
  array&lt;T,R*C&gt; _data;

  //... Constructors, etc. ...
};

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

auto mat1 = matrix&lt;int,2,2&gt;{1, 2, 3, 4};
auto mat2 = matrix&lt;int,2,2&gt;{1, 2, 3, 4, 5}; // Error! Hopefully at compile time
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

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

template<class T, std::size_t R, std::size_t C>
struct matrix {
    // 接受任意类型并进行转发:
    template<class... Args>
    matrix(Args&&... args) : _data{std::forward<Args>(args)...} {
        // 断言大小是否正确:
        static_assert(sizeof...(Args) == R * C, "初始化无效");
    }

    std::array<T, R * C> _data;
};

// 整数平方根
template<std::size_t T, std::size_t N = 0>
constexpr std::size_t isqrt() {
    if constexpr ((N+1) * (N+1) <= T) return isqrt<T, N + 1>();
    return N;
}

// 推导指南:
template<class T, class... Args>
matrix(T&&, Args&&...) ->
    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:

template &lt;class T, std::size_t R, std::size_t C&gt;
struct matrix {
    // take anything and forward it:
    template &lt;class... Args&gt;
    matrix(Args&amp;&amp;... args) : _data{std::forward&lt;Args&gt;(args)...} {
        // assert that the sizes are correct:
        static_assert(sizeof...(Args) == R * C, &quot;invalid init&quot;);
    }

    std::array&lt;T, R * C&gt; _data;
};

// integer square root
template&lt;std::size_t T, std::size_t N = 0&gt;
constexpr std::size_t isqrt() {
    if constexpr ((N+1) * (N+1) &lt;= T) return isqrt&lt;T, N + 1&gt;();
    return N;
}

// Deduction guide:
template &lt;class T, class... Args&gt;
matrix(T&amp;&amp;, Args&amp;&amp;...) -&gt;
    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:

确定