// // Copyright (C) 2011-15 DyND Developers // BSD 2-Clause License, see LICENSE.txt // #pragma once #include namespace dynd { template class iterator; template iterator begin(ContainerType &c); template iterator end(ContainerType &c); template class iterator { friend iterator begin<1, ContainerType>(ContainerType &c); friend iterator end<1, ContainerType>(ContainerType &c); protected: typedef decltype(std::begin(std::declval())) std_iterator_type; std_iterator_type m_current; std_iterator_type m_end; iterator(const std_iterator_type &begin, const std_iterator_type &end) : m_current(begin), m_end(end) { } iterator(const std_iterator_type &end) : m_current(end), m_end(end) {} public: typedef typename std::iterator_traits::value_type value_type; iterator() = default; iterator &operator++() { ++m_current; return *this; } iterator operator++(int) { iterator tmp(*this); operator++(); return tmp; } value_type &operator*() const { return *m_current; } bool operator==(const iterator &other) const { return m_current == other.m_current; } bool operator!=(const iterator &other) const { return m_current != other.m_current; } }; template class iterator : public iterator::value_type, N - 1> { typedef iterator::value_type, N - 1> base_type; friend iterator begin(ContainerType &c); friend iterator end(ContainerType &c); protected: typedef decltype(std::begin(std::declval())) std_iterator_type; std_iterator_type m_current; std_iterator_type m_end; iterator(const std_iterator_type &begin, const std_iterator_type &end, typename std::iterator_traits::value_type &front) : base_type(std::begin(front), std::end(front)), m_current(begin), m_end(end) { } iterator(const std_iterator_type &begin, const std_iterator_type &end) : iterator(begin, end, *begin) { } iterator(const std_iterator_type &end, typename std::iterator_traits::value_type &back) : base_type(std::end(back)), m_current(end), m_end(end) { } iterator(const std_iterator_type &end) : iterator(end, *std::prev(end)) {} public: typedef typename base_type::value_type value_type; iterator() = default; iterator &operator++() { base_type::operator++(); if (base_type::m_current == base_type::m_end) { ++m_current; base_type::m_current = std::begin(*m_current); base_type::m_end = std::end(*m_current); } return *this; } iterator operator++(int) { iterator tmp(*this); operator++(); return tmp; } bool operator==(const iterator &other) const { return m_current == other.m_current && base_type::operator==(other); } bool operator!=(const iterator &other) const { return m_current != other.m_current || base_type::operator!=(other); } }; template iterator begin(ContainerType &c) { return iterator(std::begin(c), std::end(c)); } template iterator end(ContainerType &c) { return iterator(std::end(c)); } template class const_iterator; template const_iterator begin(const ContainerType &c); template const_iterator end(const ContainerType &c); template class const_iterator { friend const_iterator begin<1, ContainerType>(const ContainerType &c); friend const_iterator end<1, ContainerType>(const ContainerType &c); protected: typedef decltype(std::begin(std::declval())) std_iterator_type; std_iterator_type m_current; std_iterator_type m_end; const_iterator(const std_iterator_type &begin, const std_iterator_type &end) : m_current(begin), m_end(end) { } const_iterator(const std_iterator_type &end) : m_current(end), m_end(end) {} public: typedef typename std::iterator_traits::value_type value_type; const_iterator() = default; const_iterator &operator++() { ++m_current; return *this; } const_iterator operator++(int) { const_iterator tmp(*this); operator++(); return tmp; } const value_type &operator*() const { return *m_current; } bool operator==(const const_iterator &other) const { return m_current == other.m_current; } bool operator!=(const const_iterator &other) const { return m_current != other.m_current; } }; template class const_iterator : public const_iterator::value_type, N - 1> { typedef const_iterator::value_type, N - 1> base_type; friend const_iterator begin(const ContainerType &c); friend const_iterator end(const ContainerType &c); protected: typedef decltype(std::begin(std::declval())) std_iterator_type; std_iterator_type m_current; std_iterator_type m_end; const_iterator(const std_iterator_type &begin, const std_iterator_type &end, const typename std::iterator_traits::value_type &front) : base_type(std::begin(front), std::end(front)), m_current(begin), m_end(end) { } const_iterator(const std_iterator_type &begin, const std_iterator_type &end) : const_iterator(begin, end, *begin) { } const_iterator(const std_iterator_type &end, const typename std::iterator_traits::value_type &back) : base_type(std::end(back)), m_current(end), m_end(end) { } const_iterator(const std_iterator_type &end) : const_iterator(end, *std::prev(end)) {} public: typedef typename base_type::value_type value_type; const_iterator() = default; const_iterator &operator++() { base_type::operator++(); if (base_type::m_current == base_type::m_end) { ++m_current; base_type::m_current = std::begin(*m_current); base_type::m_end = std::end(*m_current); } return *this; } const_iterator operator++(int) { const_iterator tmp(*this); operator++(); return tmp; } bool operator==(const const_iterator &other) const { return m_current == other.m_current && base_type::operator==(other); } bool operator!=(const const_iterator &other) const { return m_current != other.m_current || base_type::operator!=(other); } }; template const_iterator begin(const ContainerType &c) { return const_iterator(std::begin(c), std::end(c)); } template const_iterator end(const ContainerType &c) { return const_iterator(std::end(c)); } } // namespace dynd