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
* limitations under the License.
*
* Copyright 2010-2012 Danny Robson <danny@nerdcruft.net>
* Copyright 2010-2018 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_ITERATOR_HPP
#define __UTIL_ITERATOR_HPP
#ifndef CRUFT_UTIL_ITERATOR_HPP
#define CRUFT_UTIL_ITERATOR_HPP
#include "types/traits.hpp"
#include "variadic.hpp"
@ -288,8 +288,15 @@ namespace util {
//
// this must be expressed in terms of iterators, rather than containers,
// 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 <
typename IteratorT,
typename StoreT,
typename I = std::make_index_sequence<std::tuple_size<IteratorT>::value>
>
class collection;
@ -298,16 +305,19 @@ namespace util {
//---------------------------------------------------------------------
template <
typename IteratorT,
typename StoreT,
std::size_t ...I
>
class collection<
IteratorT,
StoreT,
std::index_sequence<I...>
> {
public:
collection (const IteratorT &_begin, const IteratorT &_end):
collection (IteratorT _begin, IteratorT _end, StoreT &&_store):
m_begin { _begin },
m_end { _end }
m_end { _end },
m_store { std::forward<StoreT> (_store) }
{ ; }
struct iterator : std::iterator<
@ -320,7 +330,7 @@ namespace util {
std::size_t
> {
public:
iterator (const IteratorT &_iterators):
iterator (IteratorT _iterators):
m_iterators (_iterators)
{ ; }
@ -381,6 +391,7 @@ namespace util {
private:
IteratorT m_begin;
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}}
template <typename ...ContainerT>
auto
zip (const ContainerT&... data)
zip (ContainerT&&... 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<
IteratorT,
decltype(store),
std::make_index_sequence<sizeof...(ContainerT)>
> {
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'}}
template <typename ...ContainerT>
auto
izip (const ContainerT&... data)
izip (ContainerT&&... data)
{
return zip (
::util::make_indices (::util::variadic::get<0> (data...)),
data...
std::forward<ContainerT> (data)...
);
}