204 lines
5.8 KiB
C
204 lines
5.8 KiB
C
|
// Iterator-related utilities.
|
||
|
// Copyright (C) 2002-2023 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
|