diff --git a/CMakeLists.txt b/CMakeLists.txt index 9689151a..21da841e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -355,7 +355,18 @@ list ( introspection.hpp io.cpp io.hpp - iterator.hpp + iterator/constant.hpp + iterator/counting.hpp + iterator/dereference.hpp + iterator/discard.hpp + iterator/indices.hpp + iterator/infix.hpp + iterator/iota.hpp + iterator/numeric.hpp + iterator/referencing.hpp + iterator/transform.hpp + iterator/unequal.hpp + iterator/zip.hpp job/fwd.hpp job/dispatch.hpp job/queue.cpp diff --git a/array/darray.hpp b/array/darray.hpp index 889029ce..c59de9c2 100644 --- a/array/darray.hpp +++ b/array/darray.hpp @@ -8,7 +8,7 @@ #pragma once -#include "../iterator.hpp" +#include "../iterator/zip.hpp" #include @@ -49,7 +49,7 @@ namespace cruft { { CHECK_LE (init.size (), CapacityV); - for (auto &&[idx, src]: cruft::izip (init)) + for (auto &&[idx, src]: cruft::iterator::izip (init)) m_data.objects[idx] = std::move (src); } diff --git a/array/sarray.hpp b/array/sarray.hpp index 3fc45ab7..561df291 100644 --- a/array/sarray.hpp +++ b/array/sarray.hpp @@ -8,7 +8,7 @@ #pragma once -#include "../iterator.hpp" +#include "../view.hpp" #include #include diff --git a/bezier.cpp b/bezier.cpp index a78f1d76..07485313 100644 --- a/bezier.cpp +++ b/bezier.cpp @@ -172,7 +172,7 @@ cruft::operator<< (std::ostream &os, const bezier &b) os << "["; std::transform (std::cbegin (b), std::cend (b), - infix_iterator (os, ", "), + iterator::infix_iterator (os, ", "), [] (auto i) { return +i; }); os << "]"; diff --git a/cmdopt.hpp b/cmdopt.hpp index 284962f3..b77aca80 100644 --- a/cmdopt.hpp +++ b/cmdopt.hpp @@ -11,7 +11,7 @@ #define CRUFT_UTIL_CMDLINE_HPP #include "introspection.hpp" -#include "iterator.hpp" +#include "iterator/infix.hpp" #include #include @@ -151,7 +151,7 @@ namespace cruft::cmdopt { std::ostringstream os; std::copy (std::cbegin (enum_traits::names), std::cend (enum_traits::names), - infix_iterator (os, "|")); + iterator::infix_iterator (os, "|")); return os.str (); } (); return EXAMPLE; diff --git a/coord/iostream.hpp b/coord/iostream.hpp index 5d07d095..6156f298 100644 --- a/coord/iostream.hpp +++ b/coord/iostream.hpp @@ -3,14 +3,13 @@ * 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 2016-2017 Danny Robson + * Copyright 2016-2019 Danny Robson */ -#ifndef CRUFT_UTIL_IOSTREAM -#define CRUFT_UTIL_IOSTREAM +#pragma once #include "./traits.hpp" -#include "../iterator.hpp" +#include "../iterator/infix.hpp" #include #include @@ -27,12 +26,10 @@ namespace cruft { os << "["; std::transform (std::cbegin (k), std::cend (k), - infix_iterator (os, ", "), + iterator::infix_iterator (os, ", "), [] (auto i) { return +i; }); os << "]"; return os; } } - -#endif diff --git a/geom/iostream.cpp b/geom/iostream.cpp index ae6d6349..7bba88a1 100644 --- a/geom/iostream.cpp +++ b/geom/iostream.cpp @@ -14,6 +14,7 @@ #include "sphere.hpp" #include "../coord/iostream.hpp" +#include "../iterator/infix.hpp" /////////////////////////////////////////////////////////////////////////////// @@ -62,7 +63,7 @@ template std::ostream& cruft::geom::operator<< (std::ostream &os, frustum val) { - return os << "[ " << cruft::make_infix (val.planes) << " ]"; + return os << "[ " << iterator::make_infix (val.planes) << " ]"; } diff --git a/iterator.hpp b/iterator.hpp deleted file mode 100644 index e56d0450..00000000 --- a/iterator.hpp +++ /dev/null @@ -1,886 +0,0 @@ -/* - * 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 "functor.hpp" -#include "types/traits.hpp" -#include "tuple/value.hpp" -#include "variadic.hpp" -#include "view.hpp" - -#include - -template -class referencing_iterator { - protected: - typedef typename std::enable_if< - is_dereferencable< - typename Base::value_type - >::value, - typename Base::value_type - >::type base_value_type; - - public: - typedef typename dereferenced_type::type value_type ; - typedef typename Base::difference_type difference_type ; - typedef value_type& reference ; - typedef value_type* pointer; - typedef typename Base::iterator_category iterator_category; - - protected: - Base m_base; - - public: - explicit referencing_iterator (Base _base): - m_base (_base) - { ; } - - referencing_iterator& operator++() { ++m_base; return *this; } - referencing_iterator operator++(int) { auto val = *this; ++m_base; return val; } - - bool operator== (const referencing_iterator &rhs) { return m_base == rhs.m_base; } - bool operator!= (const referencing_iterator &rhs) { return m_base != rhs.m_base; } - bool operator>= (const referencing_iterator &rhs) { return m_base >= rhs.m_base; } - bool operator<= (const referencing_iterator &rhs) { return m_base <= rhs.m_base; } - bool operator> (const referencing_iterator &rhs) { return m_base > rhs.m_base; } - bool operator< (const referencing_iterator &rhs) { return m_base < rhs.m_base; } - - const value_type& operator*() const - { return **m_base; } - reference operator*() - { return **m_base; } - - difference_type operator-(const referencing_iterator& rhs) const { return m_base - rhs.m_base; } - referencing_iterator operator-(int rhs) const { return referencing_iterator (m_base - rhs); } - referencing_iterator operator+(int rhs) const { return referencing_iterator (m_base + rhs); } - -}; - - -namespace cruft { - /////////////////////////////////////////////////////////////////////////// - /// an output iterator that inserts a delimiter between successive - /// assignments - /// - /// very useful for outputting comma seperated lists to an ostream, eg: - /// - /// std::copy ( - /// std::cbegin (container), - /// std::cend (container), - /// cruft::infix_iterator (os, ", ") - /// ); - template < - typename T, - class CharT = char, - class Traits = std::char_traits - > - class infix_iterator : public std::iterator { - public: - using char_type = CharT; - using traits_type = Traits; - using ostream_type = std::basic_ostream; - - infix_iterator (ostream_type& _output, const CharT *_delimiter): - m_output (_output), - m_delimiter (_delimiter) - { ; } - - infix_iterator& - operator= (T const &value) - { - if (!m_first) - m_output << m_delimiter; - - m_output << value; - m_first = false; - - return *this; - } - - infix_iterator& operator* (void) { return *this; } - infix_iterator& operator++ (void) { return *this; } - infix_iterator& operator++ (int) { return *this; } - - private: - bool m_first = true; - ostream_type &m_output; - const CharT *m_delimiter; - }; - - - namespace detail { - template - struct infix_t { - const ContainerT &_container; - const CharT *_delimiter; - }; - - template - std::ostream& - operator<< (std::ostream &os, const infix_t &val) - { - std::copy (std::cbegin (val._container), - std::cend (val._container), - infix_iterator (os, val._delimiter)); - return os; - } - - }; - - - /// a helper function that returns an object that will use a - /// cruft::infix_iterator to output a container's values to an ostream with - /// the given delimiter. - /// - /// reduces boilerplate code required to output lists of things - /// - /// std::cout << cruft::make_infix (container) << '\n'; - template - auto - make_infix (const ContainerT &_container, const CharT *_delimiter = ", ") - { - return detail::infix_t { _container, _delimiter }; - } - - - template - auto - make_infix (const ValueT (&val)[CountV]) - { - return make_infix (cruft::view {val}); - } - - - /////////////////////////////////////////////////////////////////////////// - // - template - struct numeric_iterator : public std::iterator< - typename std::iterator_traits::iterator_category, - decltype (+std::declval::value_type> ()), - typename std::iterator_traits::difference_type, - typename std::iterator_traits::pointer, - typename std::iterator_traits::reference - > { - static_assert (std::is_arithmetic_v::value_type>); - - explicit numeric_iterator (IteratorT _inner): - m_inner (_inner) - { ; } - - auto operator++ (void) { ++m_inner; return *this; } - - auto - operator- (const numeric_iterator &rhs) const - { - return typename std::iterator_traits::difference_type { m_inner - rhs.m_inner }; - } - - auto - operator* (void) const - { - return +*m_inner; - } - - auto operator== (const numeric_iterator &rhs) const { return m_inner == rhs.m_inner; } - auto operator!= (const numeric_iterator &rhs) const { return m_inner != rhs.m_inner; } - - private: - IteratorT m_inner; - }; - - - //------------------------------------------------------------------------- - // convenience function that constructs a view of numeric_iterators for a - // provided container - template - auto - numeric_view (ContainerT &data) - { - return cruft::view { - numeric_iterator (std::begin (data)), - numeric_iterator (std::end (data)) - }; - } - - - //------------------------------------------------------------------------- - template - auto - numeric_view (const ContainerT &data) - { - return cruft::view { - numeric_iterator (std::begin (data)), - numeric_iterator (std::end (data)) - }; - } - - - /////////////////////////////////////////////////////////////////////////// - /// 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: - using value_type = ValueT; - - iota (value_type _total) - : m_total (_total) - { ; } - - 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; } - - private: - ValueT m_value; - }; - - iterator begin (void) const { return iterator {}; } - iterator end (void) const { return iterator {m_total}; } - value_type size (void) const { return m_total; } - - private: - value_type m_total; - }; - - - template - iota (ValueT) -> iota; - - - /////////////////////////////////////////////////////////////////////////// - template - class indices { - public: - using value_type = std::size_t; - - indices (const ContainerT &_container): - m_container (_container) - { ; } - - class iterator { - public: - using iterator_category = std::forward_iterator_tag; - - iterator (value_type _index): - m_index (_index) - { ; } - - bool - operator!= (const iterator &rhs) const - { - return m_index != rhs.m_index; - } - - bool - operator== (const iterator &rhs) const - { - return m_index == rhs.m_index; - } - - iterator& - operator++ (void) & - { - ++m_index; - return *this; - }; - - const value_type& - operator* (void) const& - { - return m_index; - } - - private: - value_type m_index; - }; - - iterator begin (void) const { return iterator { value_type {0} }; } - iterator end (void) const { return iterator { m_container.size () }; } - - constexpr auto size (void) const noexcept - { - return std::size (m_container); - } - - private: - const ContainerT &m_container; - }; - - - template - indices (ContainerT const&) -> indices; - - - /////////////////////////////////////////////////////////////////////////// - namespace detail::zip { - /// A container that holds multiple iterators and returns a tuple of - /// their results when dereferenced. - /// - /// \tparam IteratorT A tuple-like object that contains iterators - template < - typename IteratorT, - typename = std::make_index_sequence> - > - struct zipped_iterator; - - - template - struct zipped_iterator> { - public: - // We can't declare ourselves as a forward_iterator because we're - // unable to supply references to our value_type when we get - // dereferenced unless we store the supplied values/references - // inside ourself. - // - // This complicates implementation too much given we have no - // 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 ( - std::declval () - ) - )... - >; - using reference = value_type; - using pointer = value_type*; - - - zipped_iterator (IteratorT _iterators): - m_iterators (_iterators) - { ; } - - - zipped_iterator& - operator++ (void) - { - (++std::get (m_iterators), ...); - return *this; - } - - - zipped_iterator operator++ (int); - - - auto - operator* (void) - { - // We deliberately construct a tuple manually here to reduce - // the risk of dangling references. `forward_as_tuple` and - // `make_tuple` have resulted in references to locals in the - // past. - return std::tuple< - decltype(*std::get (m_iterators))... - > ( - *std::get (m_iterators)... - ); - } - - - bool - operator== (const zipped_iterator &rhs) const - { - return m_iterators == rhs.m_iterators; - } - - - bool - operator!= (const zipped_iterator &rhs) const - { - return !(*this == rhs); - } - - - private: - IteratorT m_iterators; - }; - - - /// A simple container for multiple collections that returns a - /// wrapped multi-iterator for begin and end. - /// - /// It is up to the user to ensure StoreT does not contain dangling - /// references. - /// - /// \tparam StoreT A tuple-like object of collections (or references - /// to collections). - template - class collection { - public: - collection (StoreT&&... _store): - m_store (std::forward (_store)...) - { ; } - - using inner_t = std::tuple ()))...>; - using indices_t = std::make_index_sequence; - - using iterator = zipped_iterator; - - - iterator begin (void)& - { - return iterator ( - tuple::value::map (::cruft::functor::begin {}, m_store) - ); - } - - iterator begin (void) const& - { - return iterator ( - tuple::value::map (::cruft::functor::begin {}, m_store) - ); - } - - - iterator end (void)& - { - 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 m_store; - }; - } - - - ///------------------------------------------------------------------------ - /// Takes a variable number of container arguments and returns an interable - /// object with a value_type that is a tuple of the each container's - /// value_type. - /// - /// The returned iterator value_type is suitable for using in range-for - /// and structured bindings (and really, that's the entire point here). - /// - /// eg, cruft::zip ({1,2,3}, {4,5,6}) ~= {{1,4},{2,5},{3,6}} - template - decltype(auto) - zip (ContainerT&&... data) - { - CHECK (((std::size (data) == std::size (variadic::get<0> (data...))) && ...)); - - return detail::zip::collection ( - std::forward (data)... - ); - } - - - ///------------------------------------------------------------------------ - /// Takes a variable number of containers and returns a zipped iterable - /// object where the first of the iterator's value_types is the index of - /// that iterator. ie, It combines container offsets with value_types. - /// - /// The supplied containers _must_ not change size while the izip object - /// is live. The size of the containers may be cached for efficiency. - /// - /// eg, cruft::izip ("abc") ~= {{0,'a'},{1,'b'},{2,'c'}} - template - decltype(auto) - izip (ContainerT&&... data) - { - // Assume that all containers are the same size and create a range - // that will supply integral indices over the first container. - // - // The call to `zip` will peform more rigorous tests on the sizes - // of the container collection. - return zip ( - iota (::cruft::variadic::get<0> (data...).size ()), - std::forward (data)... - ); - } - - - /////////////////////////////////////////////////////////////////////////// - /// an output iterator that always discards any parameters on assignment. - /// - /// sometimes useful to pass to algorithms that generate useful results as - /// a return value, while not caring about the implicit OutputIterator - /// results. - struct discard_iterator : public std::iterator { - template - void operator= (const T&) { ; } - - discard_iterator& operator++ ( ) { return *this; } - discard_iterator operator++ (int) { return *this; } - discard_iterator& operator* ( ) { return *this; } - }; - - - /////////////////////////////////////////////////////////////////////////// - /// an iterator that can be infinitely incremented but never assigned. - /// - /// useful for iterator ranges where the begin iterator is an output - /// iterator and hence never reaches an end point (and where we don't want - /// to engineer the client code to account for this). - template < - typename ValueT, - typename CategoryT, - typename DistanceT, - typename PointerT, - typename ReferenceT - > - struct unequal_iterator { - using value_type = ValueT; - using iterator_category = CategoryT; - using difference_type = DistanceT; - using pointer = PointerT; - using reference = ReferenceT; - - unequal_iterator& operator++ ( ) { return *this; } - unequal_iterator operator++ (int) { return *this; } - }; - - - //------------------------------------------------------------------------- - template - auto - make_unequal_iterator (const ContainerT&) - { - using t = typename std::iterator_traits; - - return unequal_iterator< - typename t::value_type, - typename t::iterator_category, - typename t::difference_type, - typename t::pointer, - typename t::reference - > {}; - }; - - - //------------------------------------------------------------------------- - template < - typename OtherT, - - typename ValueT, - typename CategoryT, - typename DistanceT, - typename PointerT, - typename ReferenceT> - constexpr bool - operator== ( - const unequal_iterator&, - const OtherT& - ) { - return false; - } - - - //------------------------------------------------------------------------- - template < - typename OtherT, - - typename ValueT, - typename CategoryT, - typename DistanceT, - typename PointerT, - typename ReferenceT> - constexpr bool - operator== ( - const OtherT&, - const unequal_iterator& - ) { - return false; - } - - - /////////////////////////////////////////////////////////////////////////// - template - OutputIt - _transform_by_block ( - const cruft::view &, - OutputIt cursor, - FunctionT && - ) { - return cursor; - } - - - //------------------------------------------------------------------------- - template - OutputIt - _transform_by_block ( - const cruft::view &dst, - OutputIt cursor, - FunctionT &&func, - const InputT &_src, - TailT &&...tail - ) { - auto remain = _src; - if (cursor != dst.begin ()) { - auto infill = std::distance (cursor, dst.end ()); - if (remain.size () < static_cast (infill)) { - return _transform_by_block ( - dst, - std::copy_n (remain.begin (), remain.size (), cursor), - std::forward (func), - std::forward (tail)... - ); - } - - std::copy_n (remain.begin (), infill, cursor); - func (dst); - cursor = dst.begin (); - remain = { remain.begin () + infill, remain.end () }; - } - - while (remain.size () >= dst.size ()) { - std::copy_n (remain.begin (), dst.size (), dst.begin ()); - func (dst); - remain = { remain.begin () + dst.size (), remain.end () }; - } - - return _transform_by_block ( - dst, - std::copy (remain.begin (), remain.end (), cursor), - std::forward (func), - std::forward (tail)... - ); - } - - - //------------------------------------------------------------------------- - template - OutputIt - transform_by_block (const cruft::view &dst, FunctionT &&func, Args &&...src) - { - return _transform_by_block ( - dst, - dst.begin (), - std::forward (func), - std::forward (src)... - ); - } - - - /////////////////////////////////////////////////////////////////////////// - /// Counts the number of times the iterator is assigned to. - struct counting_output_iterator { - // An internal proxy value which is returned when the iterator is - // dereferenced. It increments the assignment value in the host - // iterator. - // - // The internals of this object are not a stable interface. - struct assignable { - assignable (std::size_t &_count) - : m_count (_count) - { ; } - - template - void - operator= (Arg&&) - { - ++m_count; - } - - private: - std::size_t &m_count; - }; - - using value_type = assignable; - using iterator_category = std::output_iterator_tag; - using reference = assignable&; - - counting_output_iterator& operator++ () { return *this; } - assignable operator* () { return assignable (m_count); } - - /// Returns the number of times the iterator has been assigned to. - auto count (void) const { return m_count; } - - private: - std::size_t m_count = 0; - }; - - - /////////////////////////////////////////////////////////////////////////// - /// Adapts a supplied iterator by dereferencing any operations that deal - /// with the underlying value_type of the supplied iterator. - template - struct dereference_adapter { - //--------------------------------------------------------------------- - using difference_type = typename std::iterator_traits::difference_type; - using iterator_category = typename std::iterator_traits::iterator_category; - - using value_type = std::remove_reference_t< - decltype( - *std::declval< - typename std::iterator_traits::value_type - > () - ) - >; - - using pointer = value_type*; - using reference = value_type&; - - - //--------------------------------------------------------------------- - dereference_adapter (IteratorT _cursor) - : m_cursor (_cursor) - { ; } - - - //--------------------------------------------------------------------- - // Trivial conditional operations - decltype(auto) - operator== (dereference_adapter const &rhs) const - { - return m_cursor == rhs.m_cursor; - } - - - decltype(auto) - operator!= (dereference_adapter const &rhs) const - { - return !(*this == rhs); - } - - - //--------------------------------------------------------------------- - // Iterator movement operations - dereference_adapter& - operator++ () - { - ++m_cursor; - return *this; - } - - - difference_type - operator- (dereference_adapter const &rhs) const - { - return m_cursor - rhs.m_cursor; - } - - - auto - operator+ (difference_type offset) const - { - return dereference_adapter { m_cursor + offset }; - } - - - //--------------------------------------------------------------------- - // value_type operations - decltype(auto) - operator= (value_type const &rhs) - { - return **m_cursor = rhs; - } - - decltype(auto) operator* () { return **m_cursor; } - decltype(auto) operator-> () { return **m_cursor; } - - decltype(auto) operator* () const { return **m_cursor; } - decltype(auto) operator-> () const { return **m_cursor; } - - - private: - IteratorT m_cursor; - }; - - - /////////////////////////////////////////////////////////////////////////// - namespace iterator { - template - class constant { - public: - using iterator_category = std::random_access_iterator_tag; - using value_type = ValueT; - using difference_type = std::size_t; - using pointer = value_type*; - using reference = value_type&; - - constant () = delete; - - constant (ValueT &&_value) noexcept - : m_value (std::move (_value)) - { ; } - - constant (ValueT const &_value) - : m_value (_value) - { ; } - - constant (constant const &) = default; - constant& operator= (constant const &) = default; - - constant (constant &&) = default; - constant& operator= (constant &&) = default; - - ValueT const& operator* () const& { return m_value; } - ValueT & operator* () & { return m_value; } - - ValueT const* operator-> () const & { return &m_value; } - ValueT * operator-> () & { return &m_value; } - - constant& operator++ ( ) { return *this; } - constant& operator++ (int) { return *this; } - - constant& operator-- ( ) { return *this; } - constant& operator-- (int) { return *this; } - - private: - ValueT m_value; - }; - } -}; diff --git a/iterator/constant.hpp b/iterator/constant.hpp new file mode 100644 index 00000000..79634933 --- /dev/null +++ b/iterator/constant.hpp @@ -0,0 +1,53 @@ +/* + * 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 + +/////////////////////////////////////////////////////////////////////////// +namespace cruft::iterator { + template + class constant { + public: + using iterator_category = std::random_access_iterator_tag; + using value_type = ValueT; + using difference_type = std::size_t; + using pointer = value_type*; + using reference = value_type&; + + constant () = delete; + + constant (ValueT &&_value) noexcept + : m_value (std::move (_value)) + { ; } + + constant (ValueT const &_value) + : m_value (_value) + { ; } + + constant (constant const &) = default; + constant& operator= (constant const &) = default; + + constant (constant &&) = default; + constant& operator= (constant &&) = default; + + ValueT const& operator* () const& { return m_value; } + ValueT & operator* () & { return m_value; } + + ValueT const* operator-> () const & { return &m_value; } + ValueT * operator-> () & { return &m_value; } + + constant& operator++ ( ) { return *this; } + constant& operator++ (int) { return *this; } + + constant& operator-- ( ) { return *this; } + constant& operator-- (int) { return *this; } + + private: + ValueT m_value; + }; +} diff --git a/iterator/counting.hpp b/iterator/counting.hpp new file mode 100644 index 00000000..eb4f6630 --- /dev/null +++ b/iterator/counting.hpp @@ -0,0 +1,49 @@ +/* + * 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 + +namespace cruft::iterator { + /////////////////////////////////////////////////////////////////////////// + /// Counts the number of times the iterator is assigned to. + struct counting_output_iterator { + // An internal proxy value which is returned when the iterator is + // dereferenced. It increments the assignment value in the host + // iterator. + // + // The internals of this object are not a stable interface. + struct assignable { + assignable (std::size_t &_count) + : m_count (_count) + { ; } + + template + void + operator= (Arg&&) + { + ++m_count; + } + + private: + std::size_t &m_count; + }; + + using value_type = assignable; + using iterator_category = std::output_iterator_tag; + using reference = assignable&; + + counting_output_iterator& operator++ () { return *this; } + assignable operator* () { return assignable (m_count); } + + /// Returns the number of times the iterator has been assigned to. + auto count (void) const { return m_count; } + + private: + std::size_t m_count = 0; + }; +} diff --git a/iterator/dereference.hpp b/iterator/dereference.hpp new file mode 100644 index 00000000..7192939c --- /dev/null +++ b/iterator/dereference.hpp @@ -0,0 +1,97 @@ +/* + * 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 + +namespace cruft::iterator { + /////////////////////////////////////////////////////////////////////////// + /// Adapts a supplied iterator by dereferencing any operations that deal + /// with the underlying value_type of the supplied iterator. + template + struct dereference_adapter { + //--------------------------------------------------------------------- + using difference_type = typename std::iterator_traits::difference_type; + using iterator_category = typename std::iterator_traits::iterator_category; + + using value_type = std::remove_reference_t< + decltype( + *std::declval< + typename std::iterator_traits::value_type + > () + ) + >; + + using pointer = value_type*; + using reference = value_type&; + + + //--------------------------------------------------------------------- + dereference_adapter (IteratorT _cursor) + : m_cursor (_cursor) + { ; } + + + //--------------------------------------------------------------------- + // Trivial conditional operations + decltype(auto) + operator== (dereference_adapter const &rhs) const + { + return m_cursor == rhs.m_cursor; + } + + + decltype(auto) + operator!= (dereference_adapter const &rhs) const + { + return !(*this == rhs); + } + + + //--------------------------------------------------------------------- + // Iterator movement operations + dereference_adapter& + operator++ () + { + ++m_cursor; + return *this; + } + + + difference_type + operator- (dereference_adapter const &rhs) const + { + return m_cursor - rhs.m_cursor; + } + + + auto + operator+ (difference_type offset) const + { + return dereference_adapter { m_cursor + offset }; + } + + + //--------------------------------------------------------------------- + // value_type operations + decltype(auto) + operator= (value_type const &rhs) + { + return **m_cursor = rhs; + } + + decltype(auto) operator* () { return **m_cursor; } + decltype(auto) operator-> () { return **m_cursor; } + + decltype(auto) operator* () const { return **m_cursor; } + decltype(auto) operator-> () const { return **m_cursor; } + + + private: + IteratorT m_cursor; + }; +} diff --git a/iterator/discard.hpp b/iterator/discard.hpp new file mode 100644 index 00000000..71d96cf3 --- /dev/null +++ b/iterator/discard.hpp @@ -0,0 +1,26 @@ +/* + * 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 + +namespace cruft::iterator { + /////////////////////////////////////////////////////////////////////////// + /// an output iterator that always discards any parameters on assignment. + /// + /// sometimes useful to pass to algorithms that generate useful results as + /// a return value, while not caring about the implicit OutputIterator + /// results. + struct discard_iterator : public std::iterator { + template + void operator= (const T&) { ; } + + discard_iterator& operator++ ( ) { return *this; } + discard_iterator operator++ (int) { return *this; } + discard_iterator& operator* ( ) { return *this; } + }; +} diff --git a/iterator/indices.hpp b/iterator/indices.hpp new file mode 100644 index 00000000..75854efd --- /dev/null +++ b/iterator/indices.hpp @@ -0,0 +1,74 @@ +/* + * 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 + +namespace cruft::iterator { + /////////////////////////////////////////////////////////////////////////// + template + class indices { + public: + using value_type = std::size_t; + + indices (const ContainerT &_container): + m_container (_container) + { ; } + + class iterator { + public: + using iterator_category = std::forward_iterator_tag; + + iterator (value_type _index): + m_index (_index) + { ; } + + bool + operator!= (const iterator &rhs) const + { + return m_index != rhs.m_index; + } + + bool + operator== (const iterator &rhs) const + { + return m_index == rhs.m_index; + } + + iterator& + operator++ (void) & + { + ++m_index; + return *this; + }; + + const value_type& + operator* (void) const& + { + return m_index; + } + + private: + value_type m_index; + }; + + iterator begin (void) const { return iterator { value_type {0} }; } + iterator end (void) const { return iterator { m_container.size () }; } + + constexpr auto size (void) const noexcept + { + return std::size (m_container); + } + + private: + const ContainerT &m_container; + }; + + + template + indices (ContainerT const&) -> indices; +} \ No newline at end of file diff --git a/iterator/infix.hpp b/iterator/infix.hpp new file mode 100644 index 00000000..d9eaec48 --- /dev/null +++ b/iterator/infix.hpp @@ -0,0 +1,107 @@ +/* + * 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 "../view.hpp" + +namespace cruft::iterator { + /////////////////////////////////////////////////////////////////////////// + /// an output iterator that inserts a delimiter between successive + /// assignments + /// + /// very useful for outputting comma seperated lists to an ostream, eg: + /// + /// std::copy ( + /// std::cbegin (container), + /// std::cend (container), + /// cruft::infix_iterator (os, ", ") + /// ); + template < + typename T, + class CharT = char, + class Traits = std::char_traits + > + class infix_iterator : public std::iterator { + public: + using char_type = CharT; + using traits_type = Traits; + using ostream_type = std::basic_ostream; + + infix_iterator (ostream_type& _output, const CharT *_delimiter): + m_output (_output), + m_delimiter (_delimiter) + { ; } + + infix_iterator& + operator= (T const &value) + { + if (!m_first) + m_output << m_delimiter; + + m_output << value; + m_first = false; + + return *this; + } + + infix_iterator& operator* (void) { return *this; } + infix_iterator& operator++ (void) { return *this; } + infix_iterator& operator++ (int) { return *this; } + + private: + bool m_first = true; + ostream_type &m_output; + const CharT *m_delimiter; + }; + + + namespace detail { + template + struct infix_t { + const ContainerT &_container; + const CharT *_delimiter; + }; + + template + std::ostream& + operator<< (std::ostream &os, const infix_t &val) + { + std::copy (std::cbegin (val._container), + std::cend (val._container), + infix_iterator (os, val._delimiter)); + return os; + } + + }; + + + /// a helper function that returns an object that will use a + /// cruft::infix_iterator to output a container's values to an ostream with + /// the given delimiter. + /// + /// reduces boilerplate code required to output lists of things + /// + /// std::cout << cruft::make_infix (container) << '\n'; + template + auto + make_infix (const ContainerT &_container, const CharT *_delimiter = ", ") + { + return detail::infix_t { _container, _delimiter }; + } + + + template + auto + make_infix (const ValueT (&val)[CountV]) + { + return make_infix (cruft::view {val}); + } + + +} diff --git a/iterator/iota.hpp b/iterator/iota.hpp new file mode 100644 index 00000000..f0f85d9e --- /dev/null +++ b/iterator/iota.hpp @@ -0,0 +1,76 @@ +/* + * 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 + +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: + using value_type = ValueT; + + iota (value_type _total) + : m_total (_total) + { ; } + + 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; } + + private: + ValueT m_value; + }; + + iterator begin (void) const { return iterator {}; } + iterator end (void) const { return iterator {m_total}; } + value_type size (void) const { return m_total; } + + private: + value_type m_total; + }; + + + template + iota (ValueT) -> iota; +} diff --git a/iterator/numeric.hpp b/iterator/numeric.hpp new file mode 100644 index 00000000..0df1dba8 --- /dev/null +++ b/iterator/numeric.hpp @@ -0,0 +1,64 @@ +namespace cruft::iterator { + /////////////////////////////////////////////////////////////////////////// + // + template + struct numeric_iterator : public std::iterator< + typename std::iterator_traits::iterator_category, + decltype (+std::declval::value_type> ()), + typename std::iterator_traits::difference_type, + typename std::iterator_traits::pointer, + typename std::iterator_traits::reference + > { + static_assert (std::is_arithmetic_v::value_type>); + + explicit numeric_iterator (IteratorT _inner): + m_inner (_inner) + { ; } + + auto operator++ (void) { ++m_inner; return *this; } + + auto + operator- (const numeric_iterator &rhs) const + { + return typename std::iterator_traits::difference_type { m_inner - rhs.m_inner }; + } + + auto + operator* (void) const + { + return +*m_inner; + } + + auto operator== (const numeric_iterator &rhs) const { return m_inner == rhs.m_inner; } + auto operator!= (const numeric_iterator &rhs) const { return m_inner != rhs.m_inner; } + + private: + IteratorT m_inner; + }; + + + //------------------------------------------------------------------------- + // convenience function that constructs a view of numeric_iterators for a + // provided container + template + auto + numeric_view (ContainerT &data) + { + return cruft::view { + numeric_iterator (std::begin (data)), + numeric_iterator (std::end (data)) + }; + } + + + //------------------------------------------------------------------------- + template + auto + numeric_view (const ContainerT &data) + { + return cruft::view { + numeric_iterator (std::begin (data)), + numeric_iterator (std::end (data)) + }; + } +} diff --git a/iterator/referencing.hpp b/iterator/referencing.hpp new file mode 100644 index 00000000..bd5cdfdb --- /dev/null +++ b/iterator/referencing.hpp @@ -0,0 +1,57 @@ +/* + * 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 + +namespace cruft::iterator { + template + class referencing_iterator { + protected: + typedef typename std::enable_if< + is_dereferencable< + typename Base::value_type + >::value, + typename Base::value_type + >::type base_value_type; + + public: + typedef typename dereferenced_type::type value_type ; + typedef typename Base::difference_type difference_type ; + typedef value_type& reference ; + typedef value_type* pointer; + typedef typename Base::iterator_category iterator_category; + + protected: + Base m_base; + + public: + explicit referencing_iterator (Base _base): + m_base (_base) + { ; } + + referencing_iterator& operator++() { ++m_base; return *this; } + referencing_iterator operator++(int) { auto val = *this; ++m_base; return val; } + + bool operator== (const referencing_iterator &rhs) { return m_base == rhs.m_base; } + bool operator!= (const referencing_iterator &rhs) { return m_base != rhs.m_base; } + bool operator>= (const referencing_iterator &rhs) { return m_base >= rhs.m_base; } + bool operator<= (const referencing_iterator &rhs) { return m_base <= rhs.m_base; } + bool operator> (const referencing_iterator &rhs) { return m_base > rhs.m_base; } + bool operator< (const referencing_iterator &rhs) { return m_base < rhs.m_base; } + + const value_type& operator*() const + { return **m_base; } + reference operator*() + { return **m_base; } + + difference_type operator-(const referencing_iterator& rhs) const { return m_base - rhs.m_base; } + referencing_iterator operator-(int rhs) const { return referencing_iterator (m_base - rhs); } + referencing_iterator operator+(int rhs) const { return referencing_iterator (m_base + rhs); } + + }; +} diff --git a/iterator/transform.hpp b/iterator/transform.hpp new file mode 100644 index 00000000..39e4578e --- /dev/null +++ b/iterator/transform.hpp @@ -0,0 +1,79 @@ +/* + * 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 + +namespace cruft::iterator { + /////////////////////////////////////////////////////////////////////////// + template + OutputIt + _transform_by_block ( + const cruft::view &, + OutputIt cursor, + FunctionT && + ) { + return cursor; + } + + + //------------------------------------------------------------------------- + template + OutputIt + _transform_by_block ( + const cruft::view &dst, + OutputIt cursor, + FunctionT &&func, + const InputT &_src, + TailT &&...tail + ) { + auto remain = _src; + if (cursor != dst.begin ()) { + auto infill = std::distance (cursor, dst.end ()); + if (remain.size () < static_cast (infill)) { + return _transform_by_block ( + dst, + std::copy_n (remain.begin (), remain.size (), cursor), + std::forward (func), + std::forward (tail)... + ); + } + + std::copy_n (remain.begin (), infill, cursor); + func (dst); + cursor = dst.begin (); + remain = { remain.begin () + infill, remain.end () }; + } + + while (remain.size () >= dst.size ()) { + std::copy_n (remain.begin (), dst.size (), dst.begin ()); + func (dst); + remain = { remain.begin () + dst.size (), remain.end () }; + } + + return _transform_by_block ( + dst, + std::copy (remain.begin (), remain.end (), cursor), + std::forward (func), + std::forward (tail)... + ); + } + + + //------------------------------------------------------------------------- + template + OutputIt + transform_by_block (const cruft::view &dst, FunctionT &&func, Args &&...src) + { + return _transform_by_block ( + dst, + dst.begin (), + std::forward (func), + std::forward (src)... + ); + } +}; diff --git a/iterator/unequal.hpp b/iterator/unequal.hpp new file mode 100644 index 00000000..db2fd2dd --- /dev/null +++ b/iterator/unequal.hpp @@ -0,0 +1,88 @@ +/* + * 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 + +namespace cruft::iterator { + /////////////////////////////////////////////////////////////////////////// + /// an iterator that can be infinitely incremented but never assigned. + /// + /// useful for iterator ranges where the begin iterator is an output + /// iterator and hence never reaches an end point (and where we don't want + /// to engineer the client code to account for this). + template < + typename ValueT, + typename CategoryT, + typename DistanceT, + typename PointerT, + typename ReferenceT + > + struct unequal_iterator { + using value_type = ValueT; + using iterator_category = CategoryT; + using difference_type = DistanceT; + using pointer = PointerT; + using reference = ReferenceT; + + unequal_iterator& operator++ ( ) { return *this; } + unequal_iterator operator++ (int) { return *this; } + }; + + + //------------------------------------------------------------------------- + template + auto + make_unequal_iterator (const ContainerT&) + { + using t = typename std::iterator_traits; + + return unequal_iterator< + typename t::value_type, + typename t::iterator_category, + typename t::difference_type, + typename t::pointer, + typename t::reference + > {}; + }; + + + //------------------------------------------------------------------------- + template < + typename OtherT, + + typename ValueT, + typename CategoryT, + typename DistanceT, + typename PointerT, + typename ReferenceT> + constexpr bool + operator== ( + const unequal_iterator&, + const OtherT& + ) { + return false; + } + + + //------------------------------------------------------------------------- + template < + typename OtherT, + + typename ValueT, + typename CategoryT, + typename DistanceT, + typename PointerT, + typename ReferenceT> + constexpr bool + operator== ( + const OtherT&, + const unequal_iterator& + ) { + return false; + } +} diff --git a/iterator/zip.hpp b/iterator/zip.hpp new file mode 100644 index 00000000..0d0971b3 --- /dev/null +++ b/iterator/zip.hpp @@ -0,0 +1,215 @@ +/* + * 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 "iota.hpp" +#include "../tuple/value.hpp" +#include "../variadic.hpp" +#include "../functor.hpp" + +namespace cruft::iterator { + /////////////////////////////////////////////////////////////////////////// + namespace detail::zip { + /// A container that holds multiple iterators and returns a tuple of + /// their results when dereferenced. + /// + /// \tparam IteratorT A tuple-like object that contains iterators + template < + typename IteratorT, + typename = std::make_index_sequence> + > + struct zipped_iterator; + + + template + struct zipped_iterator> { + public: + // We can't declare ourselves as a forward_iterator because we're + // unable to supply references to our value_type when we get + // dereferenced unless we store the supplied values/references + // inside ourself. + // + // This complicates implementation too much given we have no + // 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 ( + std::declval () + ) + )... + >; + using reference = value_type; + using pointer = value_type*; + + + zipped_iterator (IteratorT _iterators): + m_iterators (_iterators) + { ; } + + + zipped_iterator& + operator++ (void) + { + (++std::get (m_iterators), ...); + return *this; + } + + + zipped_iterator operator++ (int); + + + auto + operator* (void) + { + // We deliberately construct a tuple manually here to reduce + // the risk of dangling references. `forward_as_tuple` and + // `make_tuple` have resulted in references to locals in the + // past. + return std::tuple< + decltype(*std::get (m_iterators))... + > ( + *std::get (m_iterators)... + ); + } + + + bool + operator== (const zipped_iterator &rhs) const + { + return m_iterators == rhs.m_iterators; + } + + + bool + operator!= (const zipped_iterator &rhs) const + { + return !(*this == rhs); + } + + + private: + IteratorT m_iterators; + }; + + + /// A simple container for multiple collections that returns a + /// wrapped multi-iterator for begin and end. + /// + /// It is up to the user to ensure StoreT does not contain dangling + /// references. + /// + /// \tparam StoreT A tuple-like object of collections (or references + /// to collections). + template + class collection { + public: + collection (StoreT&&... _store): + m_store (std::forward (_store)...) + { ; } + + using inner_t = std::tuple ()))...>; + using indices_t = std::make_index_sequence; + + using iterator = zipped_iterator; + + + iterator begin (void)& + { + return iterator ( + tuple::value::map (::cruft::functor::begin {}, m_store) + ); + } + + iterator begin (void) const& + { + return iterator ( + tuple::value::map (::cruft::functor::begin {}, m_store) + ); + } + + + iterator end (void)& + { + 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 m_store; + }; + } + + + ///------------------------------------------------------------------------ + /// Takes a variable number of container arguments and returns an interable + /// object with a value_type that is a tuple of the each container's + /// value_type. + /// + /// The returned iterator value_type is suitable for using in range-for + /// and structured bindings (and really, that's the entire point here). + /// + /// eg, cruft::zip ({1,2,3}, {4,5,6}) ~= {{1,4},{2,5},{3,6}} + template + decltype(auto) + zip (ContainerT&&... data) + { + CHECK (((std::size (data) == std::size (variadic::get<0> (data...))) && ...)); + + return detail::zip::collection ( + std::forward (data)... + ); + } + + + ///------------------------------------------------------------------------ + /// Takes a variable number of containers and returns a zipped iterable + /// object where the first of the iterator's value_types is the index of + /// that iterator. ie, It combines container offsets with value_types. + /// + /// The supplied containers _must_ not change size while the izip object + /// is live. The size of the containers may be cached for efficiency. + /// + /// eg, cruft::izip ("abc") ~= {{0,'a'},{1,'b'},{2,'c'}} + template + decltype(auto) + izip (ContainerT&&... data) + { + // Assume that all containers are the same size and create a range + // that will supply integral indices over the first container. + // + // The call to `zip` will peform more rigorous tests on the sizes + // of the container collection. + return zip ( + iota (::cruft::variadic::get<0> (data...).size ()), + std::forward (data)... + ); + } +} diff --git a/kmeans.hpp b/kmeans.hpp index 2379340e..c0cb0299 100644 --- a/kmeans.hpp +++ b/kmeans.hpp @@ -9,7 +9,7 @@ #pragma once #include "debug.hpp" -#include "iterator.hpp" +#include "iterator/zip.hpp" #include "point.hpp" #include @@ -36,7 +36,7 @@ namespace cruft { std::fill (std::begin (accum), std::end (accum), 0); std::fill (std::begin (count), std::end (count), 0); - for (auto const& [j,p]: cruft::izip (src)) { + for (auto const& [j,p]: iterator::izip (src)) { size_t bucket = 0; for (size_t k = 1; k < dst.size (); ++k) { diff --git a/matrix.cpp b/matrix.cpp index 61331e19..a24fd03e 100644 --- a/matrix.cpp +++ b/matrix.cpp @@ -9,7 +9,7 @@ #include "matrix.hpp" #include "debug.hpp" -#include "iterator.hpp" +#include "iterator/infix.hpp" #include "point.hpp" #include diff --git a/matrix.hpp b/matrix.hpp index 62a861c1..86941a78 100644 --- a/matrix.hpp +++ b/matrix.hpp @@ -6,13 +6,12 @@ * Copyright 2011-2015 Danny Robson */ -#ifndef CRUFT_UTIL_MATRIX_HPP -#define CRUFT_UTIL_MATRIX_HPP +#pragma once #include "point.hpp" #include "range.hpp" #include "vector.hpp" -#include "iterator.hpp" +#include "iterator/infix.hpp" #include #include @@ -542,10 +541,8 @@ namespace cruft { std::copy ( std::cbegin (m), std::cend (m), - cruft::infix_iterator (os, ", ") + iterator::infix_iterator (os, ", ") ); return os << ']'; } }; - -#endif diff --git a/test/encode/base.cpp b/test/encode/base.cpp index 8d8d6ab2..af5e5c4e 100644 --- a/test/encode/base.cpp +++ b/test/encode/base.cpp @@ -1,7 +1,6 @@ #include "../../tap.hpp" #include "../../encode/base.hpp" -#include "../../iterator.hpp" /////////////////////////////////////////////////////////////////////////////// diff --git a/test/iterator.cpp b/test/iterator.cpp index ff2c5ca3..833dc7ce 100644 --- a/test/iterator.cpp +++ b/test/iterator.cpp @@ -1,6 +1,9 @@ #include "../tap.hpp" -#include "../iterator.hpp" +#include "../iterator/counting.hpp" +#include "../iterator/dereference.hpp" +#include "../iterator/iota.hpp" +#include "../iterator/zip.hpp" #include #include @@ -10,7 +13,7 @@ static void test_counting_output_iterator (cruft::TAP::logger &tap) { - cruft::counting_output_iterator out; + cruft::iterator::counting_output_iterator out; *out = 0; ++out; *out = 1; ++out; *out = 2; ++out; @@ -27,8 +30,8 @@ test_dereference_iterator (cruft::TAP::logger &tap) int const* pointers[4] = { values + 0, values + 1, values + 2, values + 3 }; auto const sum = std::accumulate ( - cruft::dereference_adapter (std::cbegin (pointers)), - cruft::dereference_adapter (std::cend (pointers)), + cruft::iterator::dereference_adapter (std::cbegin (pointers)), + cruft::iterator::dereference_adapter (std::cend (pointers)), 0 ); @@ -40,7 +43,7 @@ test_dereference_iterator (cruft::TAP::logger &tap) static void test_iota (cruft::TAP::logger &tap) { - cruft::iota seq (5); + cruft::iterator::iota seq (5); auto const sum = std::accumulate (std::begin (seq), std::end (seq), 0u); tap.expect_eq (sum, 4u+3u+2u+1u+0u, "iota summation %!", sum); } @@ -62,7 +65,7 @@ main (int, char**) char c_char[] = { '\0', 'b', 'c' }; bool success = true; - for (auto const &[i, v, a, c]: cruft::izip (v_int, a_float, c_char)) { + for (auto const &[i, v, a, c]: cruft::iterator::izip (v_int, a_float, c_char)) { success = success && v_int[i] == v && cruft::equal (a_float[i], a) && @@ -83,7 +86,7 @@ main (int, char**) const std::array src { 0, 1, 2 }; std::array dst { 2, 0, 1 }; - for (auto [a,b]: cruft::zip (src, dst)) + for (auto [a,b]: cruft::iterator::zip (src, dst)) b = a; tap.expect_eq (src, dst, "copy using structured bindings"); diff --git a/test/string.cpp b/test/string.cpp index c4dc5e5d..11056f81 100644 --- a/test/string.cpp +++ b/test/string.cpp @@ -1,7 +1,7 @@ #include "tap.hpp" #include "string.hpp" #include "types.hpp" -#include "iterator.hpp" +#include "iterator/zip.hpp" #include @@ -63,7 +63,7 @@ test_tokeniser (cruft::TAP::logger &tap) }; cruft::view src { csv.c_str (), csv.size () }; - for (auto [tok, expected]: cruft::zip (cruft::tokeniser (src, ','), TESTS)) { + for (auto [tok, expected]: cruft::iterator::zip (cruft::tokeniser (src, ','), TESTS)) { tap.expect (equal (tok, expected.value), "%s", expected.message); } } diff --git a/tools/macro.cpp b/tools/macro.cpp index cdaad298..47399a6d 100644 --- a/tools/macro.cpp +++ b/tools/macro.cpp @@ -1,5 +1,4 @@ #include "io.hpp" -#include "iterator.hpp" #include "string.hpp" #include "view.hpp" #include "cpp.hpp" diff --git a/types/comparator.hpp b/types/comparator.hpp index ba699400..01b5b278 100644 --- a/types/comparator.hpp +++ b/types/comparator.hpp @@ -11,7 +11,7 @@ #include -#include "../iterator.hpp" +#include "../iterator/zip.hpp" namespace cruft::comparator { /////////////////////////////////////////////////////////////////////////// @@ -55,7 +55,7 @@ namespace cruft::comparator { constexpr bool operator() (const T &a, const T &b) const { - for (auto x: cruft::zip (a, b)) { + for (auto x: cruft::iterator::zip (a, b)) { const auto &[i,j] = x; // BUG: clang-4.0: workaround for segfault. if (i < j) return true; if (i != j) return false; diff --git a/uri.cpp.rl b/uri.cpp.rl index c94d176b..59b54306 100644 --- a/uri.cpp.rl +++ b/uri.cpp.rl @@ -20,7 +20,6 @@ #include "uri.hpp" #include "debug.hpp" -#include "iterator.hpp" #include #include