c++ - Initialize std::array with a range (pair of iterators) -
how can initialize std::array
range (as defined pair of iterators)?
something this:
vector<t> v; ... // know v has n elements (e.g. called v.resize(n)) // want initialized elements array<t, n> a(???); // put here?
i thought array
have constructor taking pair of iterators, array<t, n> a(v.begin(), v.end())
, appears have no constructors @ all!
i know can copy
vector array, i'd rather initialize array vector contents directly, without default-constructing first. how can i?
with random access iterators, , assuming size @ compile-time, can use pack of indices 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 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 not relevant if we're assuming size n // i'll assert correct anyway assert(last - first == n); return make_array(first, buildindices<n> {}); } // usage auto = make_array<n>(v.begin(), v.end());
this assumes compiler capable of eliding intermediate copies. think assumption not big stretch.
actually, can done input iterators well, since computation of each element in braced-init-list sequenced before computation of next element (§8.5.4/4).
// internal overload 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++)... } }; }
since *first++
doesn't have i
in it, need dummy i
provoke pack expansion. comma operator rescue, void()
silence warnings lack of effects, , preventing overloaded commas.
Comments
Post a Comment