Danny Robson
58b42d5d9b
This means reduces the chances of mixing up inner/outer types, and eliminates the use of the iterator typedef within teh container.
102 lines
3.5 KiB
C++
102 lines
3.5 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* Copyright 2010-2018 Danny Robson <danny@nerdcruft.net>
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <cstddef>
|
|
#include <iterator>
|
|
|
|
namespace cruft::iterator {
|
|
///////////////////////////////////////////////////////////////////////////
|
|
/// A numeric range that supplies a sequence of values.
|
|
///
|
|
/// The value range is specified as [closed-open). ie, The last value will
|
|
/// never be output by an iterator. This makes the object suitable as a
|
|
/// means of iterating over the indices of an integrable indexed container
|
|
/// (like std::vector)
|
|
///
|
|
/// Primarily used for integrating into other utilities (like izip).
|
|
template <typename ValueT = std::size_t>
|
|
class iota {
|
|
public:
|
|
class iterator {
|
|
public:
|
|
using iterator_category = std::random_access_iterator_tag;
|
|
using value_type = ValueT const;
|
|
using difference_type = decltype (std::declval<value_type> () - std::declval<value_type> ());
|
|
using pointer = value_type*;
|
|
using reference = value_type&;
|
|
|
|
explicit iterator ()
|
|
: m_value {}
|
|
{ ; }
|
|
|
|
explicit iterator (value_type _value)
|
|
: m_value (_value)
|
|
{ ; }
|
|
|
|
pointer operator-> () const& noexcept { return &m_value; }
|
|
reference operator* () const& noexcept { return m_value; }
|
|
|
|
iterator& operator++ () noexcept { ++m_value; return *this; }
|
|
iterator& operator-- () noexcept { --m_value; return *this; }
|
|
|
|
constexpr difference_type
|
|
operator- (iterator const &rhs) const noexcept
|
|
{
|
|
return m_value - rhs.m_value;
|
|
}
|
|
|
|
constexpr bool operator!= (iterator const &rhs) const noexcept { return m_value != rhs.m_value; }
|
|
constexpr bool operator== (iterator const &rhs) const noexcept { return m_value == rhs.m_value; }
|
|
constexpr bool operator<= (iterator const &rhs) const noexcept { return m_value <= rhs.m_value; }
|
|
|
|
private:
|
|
ValueT m_value;
|
|
};
|
|
|
|
using value_type = ValueT;
|
|
using reference = ValueT&;
|
|
using const_reference = ValueT const&;
|
|
using const_iterator = iterator;
|
|
using iterator = iterator;
|
|
using difference_type = ssize_t;
|
|
using size_type = size_t;
|
|
|
|
iota ()
|
|
: m_total {}
|
|
{ ; }
|
|
|
|
iota (value_type _total)
|
|
: m_total (_total)
|
|
{ ; }
|
|
|
|
iterator begin (void) const { return iterator {}; }
|
|
iterator end (void) const { return iterator {m_total}; }
|
|
|
|
iterator cbegin (void) const { return begin (); }
|
|
iterator cend (void) const { return cend (); }
|
|
|
|
value_type size (void) const { return m_total; }
|
|
value_type max_size (void) const { return std::numeric_limits<size_type>::max (); }
|
|
bool empty (void) const noexcept { return m_total == 0; }
|
|
|
|
void swap (iota &other) { std::swap (m_total, other); }
|
|
|
|
constexpr bool operator== (iota const &rhs) const noexcept { return m_total == rhs.m_total; }
|
|
constexpr bool operator!= (iota const &rhs) const noexcept { return m_total == rhs.m_total; }
|
|
|
|
private:
|
|
value_type m_total;
|
|
};
|
|
|
|
|
|
template <typename ValueT>
|
|
iota (ValueT) -> iota<ValueT>;
|
|
}
|