在 constexpr class 的构造函数之外使用构造函数参数

Use constructor parameters outside constructor in constexpr class

我正在尝试实现类似矩阵的 class,使用 std::array 来实际存储数据。所有数据在编译时都是已知的。

我希望能够使用初始化列表来初始化 Matrix。类似于

Matrix m = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

我还希望能够在实例化期间设置矩阵的维度。

我当前的代码类似于以下内容:

template<int m, int n>
class Matrix {
public:

    using initializer_list2d = std::initializer_list< std::initializer_list<float> >;
    using array2d = std::array< std::array<float, m>, n >;

    consteval Matrix(initializer_list2d initList) {
        // static_assert to check initList length [...]

        int i = 0;
        for (auto &row : initList) {
            // static_assert to check row length [...]

            std::copy(row.begin(), row.end(), data_[i].begin());
            i++;
        }
    }

    // Definitions of operators and methods [...]
private:
    array2d data_;
};

不过为了使用它,我必须通过模板设置尺寸:

Matrix<3, 3> m = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

在我看来,由于构造函数是consteval(并且它的所有参数无论如何都必须在编译时知道)它应该以某种方式打赌可以单独通过初始化列表推导出维度。

我的应用程序无法使用动态数据类型(例如向量),因为该程序必须能够 运行 而无需访问堆。

有什么方法可以实现吗?

提前感谢您的帮助!

在 C++17 之前,没有为 class 模板推导模板参数,所以这是不可能的。

从C++17开始,你可以编写这个推导指南:

template<int m, int n>
Matrix(float const (&)[n][m]) -> Matrix<m, n>;

并在构造 Matrix:

时添加一对额外的大括号
Matrix m = 
{
 {
  {1, 2, 3},
  {4, 5, 6},
  {7, 8, 9}
 }
};

这里是 demo

我找到了另一个有趣的解决方案,使用可变参数模板:

template<int m, class T, class... U>
struct Matrix {
    Matrix(const T (&t)[m], const U (& ...u)[m]) {
        std::copy(t, t+m, arr[0]);

        int i = 0;
        (std::copy(u, u+m, arr[++i]), ...);
    }   

    T (arr[m])[sizeof...(U) + 1]; 
};

它甚至允许摆脱 cigien 的答案中所需的第二个大括号,并且不需要模板推导指南(尽管它仍然需要 C++17 才能自动推导 int m) :

Matrix mat = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

此外,编译器似乎能够对此进行相当多的优化,如所见here