【发布时间】:2021-03-18 06:34:43
【问题描述】:
我正在尝试实现类似矩阵的类,使用 std::array 来实际存储数据。所有数据在编译时都是已知的。
我希望能够使用初始化列表来初始化矩阵。类似于
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 (而且它的所有参数无论如何都必须在编译时知道),它应该以某种方式打赌可以仅通过初始化列表推断维度。
我的应用程序无法使用动态数据类型(例如向量),因为该程序必须能够在不访问堆的情况下运行。
有什么方法可以实现吗?
提前感谢您的帮助!
【问题讨论】:
-
您的构造函数的参数不必在编译时知道。即使他们这样做了(通过
consteval),你也必须处理constant evaluation happening after template instantiation。 -
你说得对,我忽略了一个事实,即“constexpr”实际上更像是对编译器的建议,如果这就是你的意思的话。我将重新表述我的部分问题。
-
我应该说的是不要错误地引用那篇论文,即不断的评估是分开的,而不是之后发生的。无论何时发生评估(在这种情况下为构造函数调用),它都无法在该过程中实例化模板。我看不出与
initializer_list对应的技术原因仍然使构造函数成为列表构造函数,但也提供大小作为模板参数,因为编译器肯定知道它有多大。在不以某种方式妥协的情况下,我不知道该怎么做。 -
非常感谢您的快速回复!我将尝试使用您提供的新信息找到解决方案,否则我可能只需要使用模板类
-
@zomnombom 请查看编辑后的答案。它被简化了一点。
标签: c++ c++11 constructor c++14 constexpr