gpt4 book ai didi

c++ - 如何从(嵌套的)std::initializer_list 确定大小?

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:00:29 24 4
gpt4 key购买 nike

C++ 的新手并试图围绕 initializer_list 进行思考。

我正在创建一个 Matrix 类,它可以有效地存储 double 值的二维数组。我没有在结构层面上了解该项目。好吧,我们创建了一个 Matrix 类,它本质上存储了一个二维数组数据。但是它需要能够存储任意大小的数组,所以它必须使用动态分配的数组。但是 std::array 是不允许的。

我不知道如何访问 i_list 中的项目。如果他们像这样传入

Matrix a = {{1, 2}, {3, 4}};

然后根据我看到的文档,我在构造函数中与该信息交互的唯一选择是 list.begin() ,它指向 {1, 2} 和​​ list.end() ,它指向{3,4}

std::vector 和 std::array 被项目描述禁止,非动态数组显然不能为大小取变量。

那么我如何让它能够读取任何大小的矩阵,以及如何从我的 i_list 中获取这些值并将它们存储到非动态的东西中?

我在想像

Matrix::Matrix(const initializer_list & list) {
double * mat[/*somehow find out size without dynamic allocation*/];
for (double* i : mat) {
*i = list[i]; //not how i_list works apparently
}
}

项目描述说:您不得为该项目使用诸如 std::array、std::vector、std::list 等库类。您必须使用动态分配的数组在内部实现 Matrix 类

最佳答案

initializer_list 是非常便宜的 [references to] 临时对象的容器。

您可以像处理数组一样遍历它们。此外,它们还有一个 size() 成员,因此您可以查询它们的尺寸。

这是将“2d”initializer_list 传递给函数(很容易成为构造函数)的示例:

#include <initializer_list>
#include <iostream>


using list_of_doubles = std::initializer_list<double>;
using list_of_list_of_doubles = std::initializer_list<list_of_doubles>;

void info(list_of_list_of_doubles lld)
{
std::cout << "{\n";
for (auto& ld : lld) {
std::cout << " {";
auto sep = " ";
for (auto& d : ld) {
std::cout << sep << d;
sep = ", ";
}
std::cout << " }\n";
}

std::cout << "}\n";
}

int main()
{
info({
{ 1,2,3 },
{ 4.0, 5.0, 6.0 }
});
}

预期输出:

{
{ 1, 2, 3 }
{ 4, 5, 6 }
}

Printing out the contents of the list is pretty simple, but what if I want to save them non-dynamically? I'm making a class constructor, and I want to have access to that data.

好的,所以要求类中的存储是非动态的(即固定大小)。

我将做一些假设:

  1. 假设目标类是一个 3x3 矩阵
  2. initializer_list 中任何未指定的项目都应假定为零。
  3. 传入超过 3 行或 3 列是逻辑错误,应该引发异常

这是(许多)方法之一:

#include <initializer_list>
#include <iostream>
#include <stdexcept>
#include <algorithm>


using list_of_doubles = std::initializer_list<double>;
using list_of_list_of_doubles = std::initializer_list<list_of_doubles>;

struct matrix
{
matrix(list_of_list_of_doubles lld)
: _storage {}
{
if (lld.size() > 3)
throw std::invalid_argument("too many rows");
auto row_idx = std::size_t { 0 };
for (auto& row : lld) {
if (row.size() > 3)
throw std::invalid_argument("too many columns");
std::copy(std::begin(row), std::end(row), std::begin(_storage[row_idx]));
++row_idx;
}
}

double _storage[3][3];
};

std::ostream& operator<<(std::ostream& os, const matrix& m)
{
std::cout << "{\n";
for (auto& ld : m._storage) {
std::cout << " {";
auto sep = " ";
for (auto& d : ld) {
std::cout << sep << d;
sep = ", ";
}
std::cout << " }\n";
}

return std::cout << "}";
}

int main()
{
matrix m({
{ 1,2,3 },
{ 4.1, 5.2, 6.3 },
{ 2.01, 4.5 } // ,0
});
std::cout << m << std::endl;

}

but I wanted a dynamically-sized 2-d array...

哦,那继续吧...

#include <initializer_list>
#include <iostream>
#include <algorithm>
#include <numeric>


using list_of_doubles = std::initializer_list<double>;
using list_of_list_of_doubles = std::initializer_list<list_of_doubles>;

std::size_t total_extent(const list_of_list_of_doubles& lld)
{
return std::accumulate(std::begin(lld), std::end(lld), std::size_t(0),
[](auto tot, auto& container) {
return tot + container.size();
});

}

struct matrix
{
using value_storage = std::unique_ptr<double[]>;
using index_storage = std::unique_ptr<std::size_t>;

matrix(list_of_list_of_doubles lld)
: _total_extent { total_extent(lld) }
, _rows { lld.size() }
, _indecies { new std::size_t[_rows] }
, _storage { new double [_total_extent] }
{
auto istorage = _storage.get();
auto iindex = _indecies.get();
for (auto& row : lld) {
*iindex++ = istorage - _storage.get();
istorage = std::copy(std::begin(row), std::end(row), istorage);
}
}

std::size_t rows() const {
return _rows;
}

const double* column(std::size_t row) const {
return std::addressof(_storage[_indecies[row]]);
}

std::size_t column_size(std::size_t row) const {
return row == _rows - 1
? _total_extent - _indecies[row]
: _indecies[row + 1] - _indecies[row];
}

std::size_t _total_extent, _rows;
std::unique_ptr<std::size_t[]> _indecies;
std::unique_ptr<double[]> _storage;
};

std::ostream& operator<<(std::ostream& os, const matrix& m)
{
std::cout << "{\n";
for (std::size_t row = 0 ; row < m.rows() ; ++row) {
std::cout << " {";
auto sep = " ";
for (std::size_t col = 0 ; col < m.column_size(row) ; ++col) {
std::cout << sep << m.column(row)[col];
sep = ", ";
}
std::cout << " }\n";
}

return std::cout << "}";
}

int main()
{
matrix m({
{ 1,2,3 },
{ 4.1, 5.2, 6.3 },
{ 2.01, 4.5 } // ,0
});
std::cout << m << std::endl;

}

关于c++ - 如何从(嵌套的)std::initializer_list 确定大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38292224/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com