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

时间:2016-07-10 13:10:14

标签: c++ arrays c++11 initializer-list

C ++新手,并试图绕过initializer_list。

我正在创建一个Matrix类,它有效地存储了一个二维数组的double值。我没有在结构层面上获得这个项目。好的我们制作一个基本上存储2D数据数组的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类

2 个答案:

答案 0 :(得分:3)

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

您可以像对待数组一样迭代它们。此外,他们还有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 }
}
  

打印出列表的内容非常简单,但是如果我想非动态地保存它们呢?我正在创建一个类构造函数,我希望能够访问这些数据。

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

我将做一些假设:

  1. 假设目标类是3x3矩阵
  2. 应该假定initializer_list中的任何非指定项都为零。
  3. 传递超过3行或列是一个逻辑错误,应该引发异常
  4. 这是一种(很多)方式:

    #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;
    
    }
    
      

    但我想要一个动态大小的二维数组...

    哦,继续......

    #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;
    
    }
    

答案 1 :(得分:0)

也许,你正在寻找这样的东西:

struct Matrix {
  Matrix(std::initializer_list<std::initializer_list<double>> m) {
    int max=0;
    for (auto l: m)
      if (m.size()>max)
        max= m.size();
    std::cout << "your matriz seems to be: " 
              << m.size() << ' ' << max << std::endl;
  }
};