如何通过 C++ 中的函数参数传递固定大小的初始化列表?
How do you pass fixed sized initializer lists of initializer lists through function parameters in C++?
我正在制作一个矩阵 class,我希望用户能够像这样实例化该矩阵:
Matrix<float, 2, 2> mat = { { 10, 20 }, { 30, 40 } };
我的矩阵 class 定义如下:
template<typename T, unsigned int ROWS, unsigned int COLS>
class Matrix
{
public:
Matrix(std::array<std::array<T, ROWS>, COLS> matrix)
{
// ...
}
// ...
};
但是,当我像上面那样尝试实例化矩阵时,编译器出现 "could not convert" 错误。我不想使用初始值设定项列表,因为我希望在用户以错误的顺序定义矩阵时触发编译时错误。有人为什么这不起作用吗?如果可以,还有其他选择吗?
std::array
只支持聚合初始化。通过使用 Matrix<float, 2, 2> mat = { ... };
语法,您请求复制初始化,std::array
只是拒绝。请注意,通过将 std::array<std::array<...>...>
作为构造函数参数,您可以使用以下初始化语法:Matrix<float, 2, 2> mat{{ 10, 20, 30, 40 }};
.
很可能,您想要的是一个 std::initializer_list
参数。
如果你想让你的 class 像 std::array
但有两个维度,你不妨做 std::array
的实现,它没有构造函数并使内部成员 public:
template<typename T, unsigned int ROWS, unsigned int COLS>
class Matrix
{
public:
T elements_[ROWS][COLS];
};
这是 stdlibc++ (gcc) 的实现:https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/array#L93. Note the declaration of _M_elems
is public (array
is a struct
here). This means that you could access _M_elems
directly if you know you are using this specific implementation of the standard library, but it's also the only way to get aggregate initialization 工作。
这也意味着您允许语法 Matrix<float, 2, 2> mat2 = { 10, 20, 40, 40 };
.
问题是 std::array
使用聚合初始化(所以可能 have/require 额外的大括号),但是你可能对 copy/move 构造函数的调用不明确 :-/
以下编译:
template <std::size_t COLS, std::size_t ROWS>
struct Matrix
{
Matrix(const std::array<std::array<float, COLS>, ROWS>&) {}
//Matrix(const std::vector<std::vector<float>>&) {}
};
int main() {
[[maybe_unused]]Matrix<3, 2> m1 = std::array{ std::array{1.f, 2.f, 3.f}, std::array{1.f, 2.f, 3.f}};
[[maybe_unused]]Matrix<3, 2> m2 ({{ {{1.f, 2.f, 3.f}}, {{1.f, 2.f, 3.f}}}});
//[[maybe_unused]]Matrix<3, 2> m3 ({ {1.f, 2.f, 3.f}, {1.f, 2.f, 3.f}}); // OK vector
}
这似乎有效...
template<typename T, unsigned int ROWS, unsigned int COLS>
class Matrix
{
public:
Matrix(const std::array<T, ROWS> (&matrix)[COLS]) {
// ...
}
};
int main() {
Matrix<float, 2, 2> mat = {{ { 10, 20 }, { 40, 40 } }};
}
尽管失败时错误消息非常糟糕,并且仅当您提供太多行或列时才会失败!...出于与 std::array<int,3> a = {1,2};
有效相同的原因...
编辑:
Matrix(const T (&matrix)[COLS][ROWS]) {}
也有效
我正在制作一个矩阵 class,我希望用户能够像这样实例化该矩阵:
Matrix<float, 2, 2> mat = { { 10, 20 }, { 30, 40 } };
我的矩阵 class 定义如下:
template<typename T, unsigned int ROWS, unsigned int COLS>
class Matrix
{
public:
Matrix(std::array<std::array<T, ROWS>, COLS> matrix)
{
// ...
}
// ...
};
但是,当我像上面那样尝试实例化矩阵时,编译器出现 "could not convert" 错误。我不想使用初始值设定项列表,因为我希望在用户以错误的顺序定义矩阵时触发编译时错误。有人为什么这不起作用吗?如果可以,还有其他选择吗?
std::array
只支持聚合初始化。通过使用 Matrix<float, 2, 2> mat = { ... };
语法,您请求复制初始化,std::array
只是拒绝。请注意,通过将 std::array<std::array<...>...>
作为构造函数参数,您可以使用以下初始化语法:Matrix<float, 2, 2> mat{{ 10, 20, 30, 40 }};
.
很可能,您想要的是一个 std::initializer_list
参数。
如果你想让你的 class 像 std::array
但有两个维度,你不妨做 std::array
的实现,它没有构造函数并使内部成员 public:
template<typename T, unsigned int ROWS, unsigned int COLS>
class Matrix
{
public:
T elements_[ROWS][COLS];
};
这是 stdlibc++ (gcc) 的实现:https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/array#L93. Note the declaration of _M_elems
is public (array
is a struct
here). This means that you could access _M_elems
directly if you know you are using this specific implementation of the standard library, but it's also the only way to get aggregate initialization 工作。
这也意味着您允许语法 Matrix<float, 2, 2> mat2 = { 10, 20, 40, 40 };
.
问题是 std::array
使用聚合初始化(所以可能 have/require 额外的大括号),但是你可能对 copy/move 构造函数的调用不明确 :-/
以下编译:
template <std::size_t COLS, std::size_t ROWS>
struct Matrix
{
Matrix(const std::array<std::array<float, COLS>, ROWS>&) {}
//Matrix(const std::vector<std::vector<float>>&) {}
};
int main() {
[[maybe_unused]]Matrix<3, 2> m1 = std::array{ std::array{1.f, 2.f, 3.f}, std::array{1.f, 2.f, 3.f}};
[[maybe_unused]]Matrix<3, 2> m2 ({{ {{1.f, 2.f, 3.f}}, {{1.f, 2.f, 3.f}}}});
//[[maybe_unused]]Matrix<3, 2> m3 ({ {1.f, 2.f, 3.f}, {1.f, 2.f, 3.f}}); // OK vector
}
这似乎有效...
template<typename T, unsigned int ROWS, unsigned int COLS>
class Matrix
{
public:
Matrix(const std::array<T, ROWS> (&matrix)[COLS]) {
// ...
}
};
int main() {
Matrix<float, 2, 2> mat = {{ { 10, 20 }, { 40, 40 } }};
}
尽管失败时错误消息非常糟糕,并且仅当您提供太多行或列时才会失败!...出于与 std::array<int,3> a = {1,2};
有效相同的原因...
编辑:
Matrix(const T (&matrix)[COLS][ROWS]) {}
也有效