【问题标题】:Initialize a n-dimensional array via initializer-list通过 initializer-list 初始化一个 n 维数组
【发布时间】:2021-04-16 12:57:02
【问题描述】:

我总是对在 C++ 中初始化默认数组感到不安,所以我想像在 python 中一样创建一个 ndarray 类。

但是我遇到了一个障碍,我找不到任何关于如何制作这种代码的信息

...
// for 1-d
ndArray(std::initializer_list<T> list){
   ...
}
// for 2-d
ndArray(std::initializer_list<std::initializer_list<T>> list){
   ...
}
// for 3-d
ndArray(std::initializer_list<std::initializer_list<std::initializer_list<T>>> list){
   ...
}
...

任何嵌套初始化列表的通用(!)

想要的结果是通过以下方式构造 ndarray:

ndArray arr = {{1,0,0},{0,1,0},{0,0,1}};

编辑: 我认为我对正确强调正确的词有点不好,但是我想在没有明确为每个维度编写代码的情况下概括这一点

编辑:

我想我现在得到了正确的想法,但还没有完全做到。 感谢@Nicholas Pilotto,但在你的情况下,它会产生这些类

// one-dimensional
ndArray<int> first;

// two-dimensional
ndArray<ndArray<int>> second; 

// .. and so on 

如果您需要 3 维数组,则需要嵌套这些数组。这对用户来说是不可取的。我认为它以某种方式涉及模板构造函数

template<typename T>
class ndArray {
    template<typename N>
    ndArray(std::initializer_list<N> list) {
        // do stuff there
    }
}

但它以某种方式涉及知道模板 N 的“深度”以确定 ndArray 的维数。也许有办法用模板做到这一点?

【问题讨论】:

  • 你只需要为一维数组实现它,提供一个带有std::initializer_list&lt;T&gt;的构造函数。如果你然后创建一个ndArray&lt;ndArray&lt;T&gt;&gt; 对象,它将提供一个std::initializer_list&lt;ndArray&lt;T&gt;&gt;(本质上是std::initializer_list&lt;T_&gt;T_ = ndArray&lt;T&gt;)构造函数,它可以满足你的需求。

标签: c++ templates containers initializer-list


【解决方案1】:

你必须定义一个接受std::initializer_list&lt;std::initializer_list&lt;T&gt;&gt;的构造函数

template <class T>
class ndArray {
    public:
    T* p;
    ndArray(initializer_list<initializer_list<T>> l) : p(new T[l.size() * l.begin()->size()]) {
        unsigned int i = 0;
        unsigned int j = 0;
        auto it = l.begin();
        auto end = l.end();
        for (; it != end; it++) {
            auto iit = (*it).begin();
            auto iend = (*it).end();
            for (; iit != iend; iit++) {
                *(p + i + j) = *iit;
                j++;
            }
            i++;
            j = i;
        }
    }
}

【讨论】:

  • 我认为问题在于如何在不为每个维度明确编写代码的情况下对其进行概括。
  • 我认为你是对的,我要编辑我的帖子
  • 离题建议:尽可能避免直接的堆内存管理。在这种情况下:考虑p 的智能指针。
  • @max66 因为比较容易理解所以我用了那个
  • std::initializer_list&lt;T&gt; 的迭代器是 T const *,但依赖它是个坏主意:如果您为另一个容器回收代码,这不一定是真的。建议:使用autoauto it = l.cbegin();auto end = l.cend();)制作对每个标准容器都有效的代码。
猜你喜欢
  • 2014-12-09
  • 1970-01-01
  • 2020-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-11
相关资源
最近更新 更多