如何通过 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 };.

Demo

问题是 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
}

Demo

这似乎有效...

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]) {}

也有效