diff options
Diffstat (limited to 'gcc/iterator-utils.h')
-rw-r--r-- | gcc/iterator-utils.h | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/gcc/iterator-utils.h b/gcc/iterator-utils.h new file mode 100644 index 0000000..22cc1a5 --- /dev/null +++ b/gcc/iterator-utils.h @@ -0,0 +1,203 @@ +// Iterator-related utilities. +// Copyright (C) 2002-2020 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. +// +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef GCC_ITERATOR_UTILS_H +#define GCC_ITERATOR_UTILS_H 1 + +// A half-open [begin, end) range of iterators. +template<typename T> +struct iterator_range +{ +public: + using const_iterator = T; + + iterator_range () = default; + iterator_range (const T &begin, const T &end) + : m_begin (begin), m_end (end) {} + + T begin () const { return m_begin; } + T end () const { return m_end; } + + explicit operator bool () const { return m_begin != m_end; } + +private: + T m_begin; + T m_end; +}; + +// Provide an iterator like BaseIT, except that it yields values of type T, +// which is derived from the type that BaseIT normally yields. +// +// The class doesn't inherit from BaseIT for two reasons: +// - using inheritance would stop the class working with plain pointers +// - not using inheritance increases type-safety for writable iterators +// +// Constructing this class from a BaseIT involves an assertion that all +// contents really do have type T. The constructor is therefore explicit. +template<typename T, typename BaseIT> +class derived_iterator +{ +public: + using value_type = T; + + derived_iterator () = default; + + template<typename... Ts> + explicit derived_iterator (Ts... args) + : m_base (std::forward<Ts> (args)...) {} + + derived_iterator &operator++ () { ++m_base; return *this; } + derived_iterator operator++ (int); + + T operator* () const { return static_cast<T> (*m_base); } + T *operator-> () const { return static_cast<T *> (m_base.operator-> ()); } + + bool operator== (const derived_iterator &other) const; + bool operator!= (const derived_iterator &other) const; + +protected: + BaseIT m_base; +}; + +template<typename T, typename BaseIT> +inline derived_iterator<T, BaseIT> +derived_iterator<T, BaseIT>::operator++ (int) +{ + derived_iterator ret = *this; + ++m_base; + return ret; +} + +template<typename T, typename BaseIT> +inline bool +derived_iterator<T, BaseIT>::operator== (const derived_iterator &other) const +{ + return m_base == other.m_base; +} + +template<typename T, typename BaseIT> +inline bool +derived_iterator<T, BaseIT>::operator!= (const derived_iterator &other) const +{ + return m_base != other.m_base; +} + +// Provide a constant view of a BaseCT in which every value is known to +// have type T, which is derived from the type that BaseCT normally presents. +// +// Constructing this class from a BaseCT involves an assertion that all +// contents really do have type T. The constructor is therefore explicit. +template<typename T, typename BaseCT> +class const_derived_container : public BaseCT +{ + using base_const_iterator = typename BaseCT::const_iterator; + +public: + using value_type = T; + using const_iterator = derived_iterator<T, base_const_iterator>; + + const_derived_container () = default; + + template<typename... Ts> + explicit const_derived_container (Ts... args) + : BaseCT (std::forward<Ts> (args)...) {} + + const_iterator begin () const { return const_iterator (BaseCT::begin ()); } + const_iterator end () const { return const_iterator (BaseCT::end ()); } + + T front () const { return static_cast<T> (BaseCT::front ()); } + T back () const { return static_cast<T> (BaseCT::back ()); } + T operator[] (unsigned int i) const; +}; + +template<typename T, typename BaseCT> +inline T +const_derived_container<T, BaseCT>::operator[] (unsigned int i) const +{ + return static_cast<T> (BaseCT::operator[] (i)); +} + +// A base class for iterators whose contents consist of a StoredT and that +// when dereferenced yield those StoredT contents as a T. Derived classes +// should implement at least operator++ or operator--. +template<typename T, typename StoredT = T> +class wrapper_iterator +{ +public: + using value_type = T; + + wrapper_iterator () = default; + + template<typename... Ts> + wrapper_iterator (Ts... args) : m_contents (std::forward<Ts> (args)...) {} + + T operator* () const { return static_cast<T> (m_contents); } + bool operator== (const wrapper_iterator &) const; + bool operator!= (const wrapper_iterator &) const; + +protected: + StoredT m_contents; +}; + +template<typename T, typename StoredT> +inline bool +wrapper_iterator<T, StoredT>::operator== (const wrapper_iterator &other) const +{ + return m_contents == other.m_contents; +} + +template<typename T, typename StoredT> +inline bool +wrapper_iterator<T, StoredT>::operator!= (const wrapper_iterator &other) const +{ + return m_contents != other.m_contents; +} + +// A forward iterator for a linked list whose nodes are referenced using +// type T. Given a node "T N", the next element is given by (N->*Next) (). +template<typename T, T *(T::*Next) () const> +class list_iterator : public wrapper_iterator<T *> +{ +private: + using parent = wrapper_iterator<T *>; + +public: + using parent::parent; + list_iterator &operator++ (); + list_iterator operator++ (int); +}; + +template<typename T, T *(T::*Next) () const> +inline list_iterator<T, Next> & +list_iterator<T, Next>::operator++ () +{ + this->m_contents = (this->m_contents->*Next) (); + return *this; +} + +template<typename T, T *(T::*Next) () const> +inline list_iterator<T, Next> +list_iterator<T, Next>::operator++ (int) +{ + list_iterator ret = *this; + this->m_contents = (this->m_contents->*Next) (); + return ret; +} + +#endif |