初始化的std ::阵列范围(对迭代器) [英] Initialize std::array with a range (pair of iterators)

查看:266
本文介绍了初始化的std ::阵列范围(对迭代器)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我怎么能初始化的std ::阵列从范围(由一对迭代器定义)?

How can I initialize an std::array from a range (as defined by a pair of iterators)?

事情是这样的:

vector<T> v;
...
// I know v has exactly N elements (e.g. I just called v.resize(N))
// Now I want a initialized with those elements
array<T, N> a(???);  // what to put here?

我觉得阵列将有一个构造以一对迭代器,这样我就可以做阵列&LT; T,N&GT;一个(v.begin(),v.end()),但它似乎在所有有没有构造函数!

I thought array would have a constructor taking a pair of iterators, so that I could do array<T, N> a(v.begin(), v.end()), but it appears to have no constructors at all!

我知道我能复制矢量到数组,但我宁愿初始化直接与向量内容的阵列,无默认构造首先它。怎么可以?

I know I can copy the vector into the array, but I'd rather initialize the array with the vector contents directly, without default-constructing it first. How can I?

推荐答案

通过随机访问迭代器,并假设在编译时有一定规模,可以使用的指数软件包这样做的:

With random access iterators, and assuming a certain size at compile-time, you can use a pack of indices to do so:

template <std::size_t... Indices>
struct indices {
    using next = indices<Indices..., sizeof...(Indices)>;
};
template <std::size_t N>
struct build_indices {
    using type = typename build_indices<N-1>::type::next;
};
template <>
struct build_indices<0> {
    using type = indices<>;
};
template <std::size_t N>
using BuildIndices = typename build_indices<N>::type;

template <typename Iterator>
using ValueType = typename std::iterator_traits<Iterator>::value_type;

// internal overload with indices tag
template <std::size_t... I, typename RandomAccessIterator,
          typename Array = std::array<ValueType<RandomAccessIterator>, sizeof...(I)>>
Array make_array(RandomAccessIterator first, indices<I...>) {
    return Array { { first[I]... } };
}

// externally visible interface
template <std::size_t N, typename RandomAccessIterator>
std::array<ValueType<RandomAccessIterator>, N>
make_array(RandomAccessIterator first, RandomAccessIterator last) {
    // last is not relevant if we're assuming the size is N
    // I'll assert it is correct anyway
    assert(last - first == N); 
    return make_array(first, BuildIndices<N> {});
}

// usage
auto a = make_array<N>(v.begin(), v.end());

这个假设能够eliding中间副本的编译器。我认为,假设是不是一个很大的拉伸。

This assumes a compiler capable of eliding the intermediate copies. I think that assumption is not a big stretch.

实际上,它可以具有输入完成迭代为好,因为在一个支撑-INIT-列表中的每个元素的计算的下一个元素(§8.5.4/ 4)的计算之前进行测序

Actually, it can be done with input iterators as well, since the computation of each element in a braced-init-list is sequenced before the computation of the next element (§8.5.4/4).

// internal overload with indices tag
template <std::size_t... I, typename InputIterator,
          typename Array = std::array<ValueType<InputIterator>, sizeof...(I)>>
Array make_array(InputIterator first, indices<I...>) {
    return Array { { (void(I), *first++)... } };
}    

由于 *第一++ 没有任何 I 在里面,我们需要一个虚拟的惹包扩展。逗号操作符来救援,用无效()沉默的警告有关缺乏的影响,同时也preventing重载逗号。

Since *first++ doesn't have any I in it, we need a dummy I to provoke the pack expansion. Comma operator to the rescue, with void() to silence warnings about lack of effects, and also preventing overloaded commas.

这篇关于初始化的std ::阵列范围(对迭代器)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆