/* * 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 */ #pragma once #include #include 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 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 () - std::declval ()); 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::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 iota (ValueT) -> iota; }