iterator: retain rvalue sources when constructing zip/izip

This commit is contained in:
Danny Robson 2018-03-23 16:40:50 +11:00
parent 86b1fa38c7
commit 490aab08bc

View File

@ -11,12 +11,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
* Copyright 2010-2012 Danny Robson <danny@nerdcruft.net> * Copyright 2010-2018 Danny Robson <danny@nerdcruft.net>
*/ */
#ifndef __UTIL_ITERATOR_HPP #ifndef CRUFT_UTIL_ITERATOR_HPP
#define __UTIL_ITERATOR_HPP #define CRUFT_UTIL_ITERATOR_HPP
#include "types/traits.hpp" #include "types/traits.hpp"
#include "variadic.hpp" #include "variadic.hpp"
@ -288,8 +288,15 @@ namespace util {
// //
// this must be expressed in terms of iterators, rather than containers, // this must be expressed in terms of iterators, rather than containers,
// because it dramatically simplifies iterating over raw arrays. // because it dramatically simplifies iterating over raw arrays.
//
// IteratorT: a tuple of iterators across all containers
//
// StoreT: a tuple of containers we own. used when we were provided
// with an rval at zip time. allows us to destroy the data
// when we're actually done iterating.
template < template <
typename IteratorT, typename IteratorT,
typename StoreT,
typename I = std::make_index_sequence<std::tuple_size<IteratorT>::value> typename I = std::make_index_sequence<std::tuple_size<IteratorT>::value>
> >
class collection; class collection;
@ -298,16 +305,19 @@ namespace util {
//--------------------------------------------------------------------- //---------------------------------------------------------------------
template < template <
typename IteratorT, typename IteratorT,
typename StoreT,
std::size_t ...I std::size_t ...I
> >
class collection< class collection<
IteratorT, IteratorT,
StoreT,
std::index_sequence<I...> std::index_sequence<I...>
> { > {
public: public:
collection (const IteratorT &_begin, const IteratorT &_end): collection (IteratorT _begin, IteratorT _end, StoreT &&_store):
m_begin { _begin }, m_begin { _begin },
m_end { _end } m_end { _end },
m_store { std::forward<StoreT> (_store) }
{ ; } { ; }
struct iterator : std::iterator< struct iterator : std::iterator<
@ -320,7 +330,7 @@ namespace util {
std::size_t std::size_t
> { > {
public: public:
iterator (const IteratorT &_iterators): iterator (IteratorT _iterators):
m_iterators (_iterators) m_iterators (_iterators)
{ ; } { ; }
@ -381,6 +391,7 @@ namespace util {
private: private:
IteratorT m_begin; IteratorT m_begin;
IteratorT m_end; IteratorT m_end;
const StoreT m_store;
}; };
} }
@ -395,16 +406,20 @@ namespace util {
/// eg, util::zip ({1,2,3}, {4,5,6}) ~= {{1,4},{2,5},{3,6}} /// eg, util::zip ({1,2,3}, {4,5,6}) ~= {{1,4},{2,5},{3,6}}
template <typename ...ContainerT> template <typename ...ContainerT>
auto auto
zip (const ContainerT&... data) zip (ContainerT&&... data)
{ {
using IteratorT = std::tuple<decltype(std::begin(data))...>; using IteratorT = std::tuple<decltype(std::begin(data))...>;
auto store = util::variadic::filter<std::is_rvalue_reference> (std::forward<ContainerT> (data)...);
return detail::zip::collection< return detail::zip::collection<
IteratorT, IteratorT,
decltype(store),
std::make_index_sequence<sizeof...(ContainerT)> std::make_index_sequence<sizeof...(ContainerT)>
> { > {
std::make_tuple (std::begin (data)...), std::make_tuple (std::begin (data)...),
std::make_tuple (std::end (data)...) std::make_tuple (std::end (data)...),
std::move (store)
}; };
}; };
@ -417,11 +432,11 @@ namespace util {
/// eg, util::izip ("abc") ~= {{0,'a'},{1,'b'},{2,'c'}} /// eg, util::izip ("abc") ~= {{0,'a'},{1,'b'},{2,'c'}}
template <typename ...ContainerT> template <typename ...ContainerT>
auto auto
izip (const ContainerT&... data) izip (ContainerT&&... data)
{ {
return zip ( return zip (
::util::make_indices (::util::variadic::get<0> (data...)), ::util::make_indices (::util::variadic::get<0> (data...)),
data... std::forward<ContainerT> (data)...
); );
} }