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