【问题标题】:Is it possible to create std::array using begin() and end()?是否可以使用 begin() 和 end() 创建 std::array?
【发布时间】:2016-12-06 17:05:07
【问题描述】:
std::array<int, 4> myarray = {1, 2, 3, 4};
std::array<int, 4> myarray2(std::begin(myarray),std::end(myarray)); //It throws error

如果我可以创建myarray2 的唯一方法是将两个std::array&lt;int, 4&gt;::iterator 传递给构造函数,我是否可以使用std::array 来实现它,还是必须使用vector

【问题讨论】:

  • 查看一些基本参考资料会发现构造函数是隐式声明的,并且必须遵循聚合初始化的规则。由于这不包括迭代器,所以答案是否定的。请记住,std::array 代表一个固定/静态数组,就像传统的 C 样式数组一样。
  • 既然你知道数组的大小,你可以计算*std::begin(myarray)*std::next(std::begin(myarray))等,并使用通常的聚合语法std::array&lt;int, 4&gt; myarray2{a,b,c,d};构建myarray2。

标签: c++ arrays constructor


【解决方案1】:
template<class T, std::size_t N, class It>
std::array<T,N> array_from_iterator(It it){
  return indexer<N>()(
    [it](auto...Is)->std::array<T,N>
    {
      return { (*(it+Is))... };
    }
  );
}

indexer 在哪里:

template<class=void,std::size_t...Is>
auto indexer(std::index_sequence<Is...>){
  return [](auto&&f)->decltype(auto){
    return decltype(f)(f)( std::integral_constant<std::size_t,Is>{}... );
  };
}
template<std::size_t N>
auto indexer(){
  return indexer(std::make_index_sequence<N>{});
}

为我们做了哪些参数包扩展。没有边界检查。未编译,可能有 tpyos。

C++14,我不保证 MSVC 可以正常工作。

std::array<int, 4> myarray2 = array_from_iterator<int,4>(std::begin(myarray));

可以修改为与我怀疑的非随机访问迭代器一起使用。

【讨论】:

    【解决方案2】:

    您可以定义您的 custom_array,它继承自标准 std::array。

     template<typename _T, size_t _size>
        class custom_array : public std::array<_T, _size> {
        public:
            custom_array(std::array<_T, _size> arr, 
                         size_t start, 
                         size_t end) {
    
                size_t itr = 0;
    
                while (itr < this->size() &&
                       start < arr.size() && 
                       start <= end) {
                    this->_Elems[itr++] = arr[start++];
                }
            }
    
            custom_array(std::array<_T, _size>::iterator start,
                         std::array<_T, _size>::iterator end) {
                size_t itr = 0;
                while (itr < this->size()) {
                    this->_Elems[itr++] = *start;
                    start++;
                    if (start == end) { break; }
                }
            }
        };
    

    然后你可以随意声明你的custom_array,例如:

    std::array<int, 4> arr = { 1, 2, 3, 4 };
    custom_array<int, 4> arr_1(a, 0, 4);
    custom_array<int, 4> arr_2(a.begin(), a.end());
    

    【讨论】:

    • 这样做(继承)的明显缺点是您失去了std::array 的聚合状态,这是它的主要优点之一。 Aggregates cannot have base classes.
    • 你能举个具体的例子吗?
    • 我不明白你的意思。聚合的具体例子? std::array 是一个聚合类型。当您继承它时,您将失去该状态;您的派生类custom_array 不是 聚合。有关什么是聚合以及它们的特殊之处的更多信息,请参阅here
    猜你喜欢
    • 2012-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 2011-10-16
    • 1970-01-01
    相关资源
    最近更新 更多