iterator: add full iterator_traits for cruft::zip

This commit is contained in:
Danny Robson 2019-02-05 11:58:57 +11:00
parent 9982ea2bb7
commit a2592edc53

View File

@ -8,6 +8,7 @@
#pragma once
#include "functor.hpp"
#include "types/traits.hpp"
#include "tuple/value.hpp"
#include "variadic.hpp"
@ -332,11 +333,11 @@ namespace cruft {
typename IteratorT,
typename = std::make_index_sequence<std::tuple_size_v<IteratorT>>
>
struct iterator;
struct zipped_iterator;
template <typename IteratorT, std::size_t ...Indices>
struct iterator<IteratorT, std::index_sequence<Indices...>> {
struct zipped_iterator<IteratorT, std::index_sequence<Indices...>> {
public:
// We can't declare ourselves as a forward_iterator because we're
// unable to supply references to our value_type when we get
@ -347,13 +348,23 @@ namespace cruft {
// pressing need for this functionality.
using iterator_category = std::input_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = std::tuple<
decltype(
*std::get<Indices> (
std::declval<IteratorT> ()
)
)...
>;
using reference = value_type;
using pointer = value_type*;
iterator (IteratorT _iterators):
zipped_iterator (IteratorT _iterators):
m_iterators (_iterators)
{ ; }
iterator&
zipped_iterator&
operator++ (void)
{
(++std::get<Indices> (m_iterators), ...);
@ -361,7 +372,7 @@ namespace cruft {
}
iterator operator++ (int);
zipped_iterator operator++ (int);
auto
@ -380,14 +391,14 @@ namespace cruft {
bool
operator== (const iterator &rhs) const
operator== (const zipped_iterator &rhs) const
{
return m_iterators == rhs.m_iterators;
}
bool
operator!= (const iterator &rhs) const
operator!= (const zipped_iterator &rhs) const
{
return !(*this == rhs);
}
@ -413,34 +424,53 @@ namespace cruft {
m_store (std::forward<StoreT> (_store)...)
{ ; }
using inner_t = std::tuple<decltype(std::begin (std::declval<StoreT> ()))...>;
using indices_t = std::make_index_sequence<sizeof...(StoreT)>;
using indices_t = std::make_index_sequence<sizeof...(StoreT)>;
using begin_t = std::tuple<decltype(std::begin (std::declval<StoreT> ()))...>;
using end_t = std::tuple<decltype(std::end (std::declval<StoreT> ()))...>;
using iterator = zipped_iterator<inner_t, indices_t>;
auto begin (void)&
iterator begin (void)&
{
return iterator<begin_t, indices_t> (
tuple::value::map (
[] (auto &i) noexcept { return std::begin (i); },
m_store
)
return iterator (
tuple::value::map (::cruft::functor::begin {}, m_store)
);
}
iterator begin (void) const&
{
return iterator (
tuple::value::map (::cruft::functor::begin {}, m_store)
);
}
auto end (void)&
iterator end (void)&
{
return iterator<end_t, indices_t> (
tuple::value::map (
[] (auto &i) noexcept { return std::end (i); },
m_store
)
return iterator (
tuple::value::map (cruft::functor::end {}, m_store)
);
}
iterator end (void) const &
{
return iterator (
tuple::value::map (cruft::functor::end {}, m_store)
);
}
/// Returns the number of elements in the sequence.
decltype (auto)
size (void) const
{
// All stores should have the same size so we arbitrarily pick
// the first to query.
return std::get<0> (m_store).size ();
}
private:
std::tuple<StoreT...> m_store;
};