在 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
我正在尝试实现类似矩阵的 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