You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
552 lines
17 KiB
C++
552 lines
17 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef ITERATORS_H
|
|
#define ITERATORS_H
|
|
|
|
#include <iterator>
|
|
#include <stdexcept>
|
|
#include <cstddef>
|
|
#include <cassert>
|
|
|
|
#include "test_macros.h"
|
|
|
|
#if TEST_STD_VER >= 11
|
|
#define DELETE_FUNCTION = delete
|
|
#else
|
|
#define DELETE_FUNCTION
|
|
#endif
|
|
|
|
template <class It>
|
|
class output_iterator
|
|
{
|
|
It it_;
|
|
|
|
template <class U> friend class output_iterator;
|
|
public:
|
|
typedef std::output_iterator_tag iterator_category;
|
|
typedef void value_type;
|
|
typedef typename std::iterator_traits<It>::difference_type difference_type;
|
|
typedef It pointer;
|
|
typedef typename std::iterator_traits<It>::reference reference;
|
|
|
|
It base() const {return it_;}
|
|
|
|
output_iterator () {}
|
|
explicit output_iterator(It it) : it_(it) {}
|
|
template <class U>
|
|
output_iterator(const output_iterator<U>& u) :it_(u.it_) {}
|
|
|
|
reference operator*() const {return *it_;}
|
|
|
|
output_iterator& operator++() {++it_; return *this;}
|
|
output_iterator operator++(int)
|
|
{output_iterator tmp(*this); ++(*this); return tmp;}
|
|
|
|
template <class T>
|
|
void operator,(T const &) DELETE_FUNCTION;
|
|
};
|
|
|
|
template <class It,
|
|
class ItTraits = It>
|
|
class input_iterator
|
|
{
|
|
typedef std::iterator_traits<ItTraits> Traits;
|
|
It it_;
|
|
|
|
template <class U, class T> friend class input_iterator;
|
|
public:
|
|
typedef std::input_iterator_tag iterator_category;
|
|
typedef typename Traits::value_type value_type;
|
|
typedef typename Traits::difference_type difference_type;
|
|
typedef It pointer;
|
|
typedef typename Traits::reference reference;
|
|
|
|
TEST_CONSTEXPR_CXX14 It base() const {return it_;}
|
|
|
|
TEST_CONSTEXPR_CXX14 input_iterator() : it_() {}
|
|
explicit TEST_CONSTEXPR_CXX14 input_iterator(It it) : it_(it) {}
|
|
template <class U, class T>
|
|
TEST_CONSTEXPR_CXX14 input_iterator(const input_iterator<U, T>& u) :it_(u.it_) {}
|
|
|
|
TEST_CONSTEXPR_CXX14 reference operator*() const {return *it_;}
|
|
TEST_CONSTEXPR_CXX14 pointer operator->() const {return it_;}
|
|
|
|
TEST_CONSTEXPR_CXX14 input_iterator& operator++() {++it_; return *this;}
|
|
TEST_CONSTEXPR_CXX14 input_iterator operator++(int)
|
|
{input_iterator tmp(*this); ++(*this); return tmp;}
|
|
|
|
friend TEST_CONSTEXPR_CXX14 bool operator==(const input_iterator& x, const input_iterator& y)
|
|
{return x.it_ == y.it_;}
|
|
friend TEST_CONSTEXPR_CXX14 bool operator!=(const input_iterator& x, const input_iterator& y)
|
|
{return !(x == y);}
|
|
|
|
template <class T>
|
|
void operator,(T const &) DELETE_FUNCTION;
|
|
};
|
|
|
|
template <class T, class TV, class U, class UV>
|
|
inline
|
|
bool
|
|
operator==(const input_iterator<T, TV>& x, const input_iterator<U, UV>& y)
|
|
{
|
|
return x.base() == y.base();
|
|
}
|
|
|
|
template <class T, class TV, class U, class UV>
|
|
inline
|
|
bool
|
|
operator!=(const input_iterator<T, TV>& x, const input_iterator<U, UV>& y)
|
|
{
|
|
return !(x == y);
|
|
}
|
|
|
|
template <class It>
|
|
class forward_iterator
|
|
{
|
|
It it_;
|
|
|
|
template <class U> friend class forward_iterator;
|
|
public:
|
|
typedef std::forward_iterator_tag iterator_category;
|
|
typedef typename std::iterator_traits<It>::value_type value_type;
|
|
typedef typename std::iterator_traits<It>::difference_type difference_type;
|
|
typedef It pointer;
|
|
typedef typename std::iterator_traits<It>::reference reference;
|
|
|
|
TEST_CONSTEXPR_CXX14 It base() const {return it_;}
|
|
|
|
TEST_CONSTEXPR_CXX14 forward_iterator() : it_() {}
|
|
explicit TEST_CONSTEXPR_CXX14 forward_iterator(It it) : it_(it) {}
|
|
template <class U>
|
|
TEST_CONSTEXPR_CXX14 forward_iterator(const forward_iterator<U>& u) :it_(u.it_) {}
|
|
|
|
TEST_CONSTEXPR_CXX14 reference operator*() const {return *it_;}
|
|
TEST_CONSTEXPR_CXX14 pointer operator->() const {return it_;}
|
|
|
|
TEST_CONSTEXPR_CXX14 forward_iterator& operator++() {++it_; return *this;}
|
|
TEST_CONSTEXPR_CXX14 forward_iterator operator++(int)
|
|
{forward_iterator tmp(*this); ++(*this); return tmp;}
|
|
|
|
friend TEST_CONSTEXPR_CXX14 bool operator==(const forward_iterator& x, const forward_iterator& y)
|
|
{return x.it_ == y.it_;}
|
|
friend TEST_CONSTEXPR_CXX14 bool operator!=(const forward_iterator& x, const forward_iterator& y)
|
|
{return !(x == y);}
|
|
|
|
template <class T>
|
|
void operator,(T const &) DELETE_FUNCTION;
|
|
};
|
|
|
|
template <class T, class U>
|
|
inline
|
|
bool TEST_CONSTEXPR_CXX14
|
|
operator==(const forward_iterator<T>& x, const forward_iterator<U>& y)
|
|
{
|
|
return x.base() == y.base();
|
|
}
|
|
|
|
template <class T, class U>
|
|
inline
|
|
bool TEST_CONSTEXPR_CXX14
|
|
operator!=(const forward_iterator<T>& x, const forward_iterator<U>& y)
|
|
{
|
|
return !(x == y);
|
|
}
|
|
|
|
template <class It>
|
|
class bidirectional_iterator
|
|
{
|
|
It it_;
|
|
|
|
template <class U> friend class bidirectional_iterator;
|
|
public:
|
|
typedef std::bidirectional_iterator_tag iterator_category;
|
|
typedef typename std::iterator_traits<It>::value_type value_type;
|
|
typedef typename std::iterator_traits<It>::difference_type difference_type;
|
|
typedef It pointer;
|
|
typedef typename std::iterator_traits<It>::reference reference;
|
|
|
|
TEST_CONSTEXPR_CXX14 It base() const {return it_;}
|
|
|
|
TEST_CONSTEXPR_CXX14 bidirectional_iterator() : it_() {}
|
|
explicit TEST_CONSTEXPR_CXX14 bidirectional_iterator(It it) : it_(it) {}
|
|
template <class U>
|
|
TEST_CONSTEXPR_CXX14 bidirectional_iterator(const bidirectional_iterator<U>& u) :it_(u.it_) {}
|
|
|
|
TEST_CONSTEXPR_CXX14 reference operator*() const {return *it_;}
|
|
TEST_CONSTEXPR_CXX14 pointer operator->() const {return it_;}
|
|
|
|
TEST_CONSTEXPR_CXX14 bidirectional_iterator& operator++() {++it_; return *this;}
|
|
TEST_CONSTEXPR_CXX14 bidirectional_iterator operator++(int)
|
|
{bidirectional_iterator tmp(*this); ++(*this); return tmp;}
|
|
|
|
TEST_CONSTEXPR_CXX14 bidirectional_iterator& operator--() {--it_; return *this;}
|
|
TEST_CONSTEXPR_CXX14 bidirectional_iterator operator--(int)
|
|
{bidirectional_iterator tmp(*this); --(*this); return tmp;}
|
|
|
|
template <class T>
|
|
void operator,(T const &) DELETE_FUNCTION;
|
|
};
|
|
|
|
template <class T, class U>
|
|
inline
|
|
bool TEST_CONSTEXPR_CXX14
|
|
operator==(const bidirectional_iterator<T>& x, const bidirectional_iterator<U>& y)
|
|
{
|
|
return x.base() == y.base();
|
|
}
|
|
|
|
template <class T, class U>
|
|
inline
|
|
bool TEST_CONSTEXPR_CXX14
|
|
operator!=(const bidirectional_iterator<T>& x, const bidirectional_iterator<U>& y)
|
|
{
|
|
return !(x == y);
|
|
}
|
|
|
|
template <class It>
|
|
class random_access_iterator
|
|
{
|
|
It it_;
|
|
|
|
template <class U> friend class random_access_iterator;
|
|
public:
|
|
typedef std::random_access_iterator_tag iterator_category;
|
|
typedef typename std::iterator_traits<It>::value_type value_type;
|
|
typedef typename std::iterator_traits<It>::difference_type difference_type;
|
|
typedef It pointer;
|
|
typedef typename std::iterator_traits<It>::reference reference;
|
|
|
|
TEST_CONSTEXPR_CXX14 It base() const {return it_;}
|
|
|
|
TEST_CONSTEXPR_CXX14 random_access_iterator() : it_() {}
|
|
explicit TEST_CONSTEXPR_CXX14 random_access_iterator(It it) : it_(it) {}
|
|
template <class U>
|
|
TEST_CONSTEXPR_CXX14 random_access_iterator(const random_access_iterator<U>& u) :it_(u.it_) {}
|
|
|
|
TEST_CONSTEXPR_CXX14 reference operator*() const {return *it_;}
|
|
TEST_CONSTEXPR_CXX14 pointer operator->() const {return it_;}
|
|
|
|
TEST_CONSTEXPR_CXX14 random_access_iterator& operator++() {++it_; return *this;}
|
|
TEST_CONSTEXPR_CXX14 random_access_iterator operator++(int)
|
|
{random_access_iterator tmp(*this); ++(*this); return tmp;}
|
|
|
|
TEST_CONSTEXPR_CXX14 random_access_iterator& operator--() {--it_; return *this;}
|
|
TEST_CONSTEXPR_CXX14 random_access_iterator operator--(int)
|
|
{random_access_iterator tmp(*this); --(*this); return tmp;}
|
|
|
|
TEST_CONSTEXPR_CXX14 random_access_iterator& operator+=(difference_type n) {it_ += n; return *this;}
|
|
TEST_CONSTEXPR_CXX14 random_access_iterator operator+(difference_type n) const
|
|
{random_access_iterator tmp(*this); tmp += n; return tmp;}
|
|
friend TEST_CONSTEXPR_CXX14 random_access_iterator operator+(difference_type n, random_access_iterator x)
|
|
{x += n; return x;}
|
|
TEST_CONSTEXPR_CXX14 random_access_iterator& operator-=(difference_type n) {return *this += -n;}
|
|
TEST_CONSTEXPR_CXX14 random_access_iterator operator-(difference_type n) const
|
|
{random_access_iterator tmp(*this); tmp -= n; return tmp;}
|
|
|
|
TEST_CONSTEXPR_CXX14 reference operator[](difference_type n) const {return it_[n];}
|
|
|
|
template <class T>
|
|
void operator,(T const &) DELETE_FUNCTION;
|
|
};
|
|
|
|
template <class T, class U>
|
|
inline
|
|
bool TEST_CONSTEXPR_CXX14
|
|
operator==(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
|
|
{
|
|
return x.base() == y.base();
|
|
}
|
|
|
|
template <class T, class U>
|
|
inline
|
|
bool TEST_CONSTEXPR_CXX14
|
|
operator!=(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
|
|
{
|
|
return !(x == y);
|
|
}
|
|
|
|
template <class T, class U>
|
|
inline
|
|
bool TEST_CONSTEXPR_CXX14
|
|
operator<(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
|
|
{
|
|
return x.base() < y.base();
|
|
}
|
|
|
|
template <class T, class U>
|
|
inline
|
|
bool TEST_CONSTEXPR_CXX14
|
|
operator<=(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
|
|
{
|
|
return !(y < x);
|
|
}
|
|
|
|
template <class T, class U>
|
|
inline
|
|
bool TEST_CONSTEXPR_CXX14
|
|
operator>(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
|
|
{
|
|
return y < x;
|
|
}
|
|
|
|
template <class T, class U>
|
|
inline
|
|
bool TEST_CONSTEXPR_CXX14
|
|
operator>=(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
|
|
{
|
|
return !(x < y);
|
|
}
|
|
|
|
template <class T, class U>
|
|
inline TEST_CONSTEXPR_CXX14
|
|
typename std::iterator_traits<T>::difference_type
|
|
operator-(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
|
|
{
|
|
return x.base() - y.base();
|
|
}
|
|
|
|
template <class Iter>
|
|
inline TEST_CONSTEXPR_CXX14 Iter base(output_iterator<Iter> i) { return i.base(); }
|
|
|
|
template <class Iter>
|
|
inline TEST_CONSTEXPR_CXX14 Iter base(input_iterator<Iter> i) { return i.base(); }
|
|
|
|
template <class Iter>
|
|
inline TEST_CONSTEXPR_CXX14 Iter base(forward_iterator<Iter> i) { return i.base(); }
|
|
|
|
template <class Iter>
|
|
inline TEST_CONSTEXPR_CXX14 Iter base(bidirectional_iterator<Iter> i) { return i.base(); }
|
|
|
|
template <class Iter>
|
|
inline TEST_CONSTEXPR_CXX14 Iter base(random_access_iterator<Iter> i) { return i.base(); }
|
|
|
|
template <class Iter> // everything else
|
|
inline TEST_CONSTEXPR_CXX14 Iter base(Iter i) { return i; }
|
|
|
|
template <typename T>
|
|
struct ThrowingIterator {
|
|
typedef std::bidirectional_iterator_tag iterator_category;
|
|
typedef ptrdiff_t difference_type;
|
|
typedef const T value_type;
|
|
typedef const T * pointer;
|
|
typedef const T & reference;
|
|
|
|
enum ThrowingAction { TAIncrement, TADecrement, TADereference, TAAssignment, TAComparison };
|
|
|
|
// Constructors
|
|
ThrowingIterator ()
|
|
: begin_(nullptr), end_(nullptr), current_(nullptr), action_(TADereference), index_(0) {}
|
|
ThrowingIterator (const T *first, const T *last, size_t index = 0, ThrowingAction action = TADereference)
|
|
: begin_(first), end_(last), current_(first), action_(action), index_(index) {}
|
|
ThrowingIterator (const ThrowingIterator &rhs)
|
|
: begin_(rhs.begin_), end_(rhs.end_), current_(rhs.current_), action_(rhs.action_), index_(rhs.index_) {}
|
|
ThrowingIterator & operator= (const ThrowingIterator &rhs)
|
|
{
|
|
if (action_ == TAAssignment)
|
|
{
|
|
if (index_ == 0)
|
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
|
throw std::runtime_error ("throw from iterator assignment");
|
|
#else
|
|
assert(false);
|
|
#endif
|
|
|
|
else
|
|
--index_;
|
|
}
|
|
begin_ = rhs.begin_;
|
|
end_ = rhs.end_;
|
|
current_ = rhs.current_;
|
|
action_ = rhs.action_;
|
|
index_ = rhs.index_;
|
|
return *this;
|
|
}
|
|
|
|
// iterator operations
|
|
reference operator*() const
|
|
{
|
|
if (action_ == TADereference)
|
|
{
|
|
if (index_ == 0)
|
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
|
throw std::runtime_error ("throw from iterator dereference");
|
|
#else
|
|
assert(false);
|
|
#endif
|
|
else
|
|
--index_;
|
|
}
|
|
return *current_;
|
|
}
|
|
|
|
ThrowingIterator & operator++()
|
|
{
|
|
if (action_ == TAIncrement)
|
|
{
|
|
if (index_ == 0)
|
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
|
throw std::runtime_error ("throw from iterator increment");
|
|
#else
|
|
assert(false);
|
|
#endif
|
|
else
|
|
--index_;
|
|
}
|
|
++current_;
|
|
return *this;
|
|
}
|
|
|
|
ThrowingIterator operator++(int)
|
|
{
|
|
ThrowingIterator temp = *this;
|
|
++(*this);
|
|
return temp;
|
|
}
|
|
|
|
ThrowingIterator & operator--()
|
|
{
|
|
if (action_ == TADecrement)
|
|
{
|
|
if (index_ == 0)
|
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
|
throw std::runtime_error ("throw from iterator decrement");
|
|
#else
|
|
assert(false);
|
|
#endif
|
|
else
|
|
--index_;
|
|
}
|
|
--current_;
|
|
return *this;
|
|
}
|
|
|
|
ThrowingIterator operator--(int) {
|
|
ThrowingIterator temp = *this;
|
|
--(*this);
|
|
return temp;
|
|
}
|
|
|
|
bool operator== (const ThrowingIterator &rhs) const
|
|
{
|
|
if (action_ == TAComparison)
|
|
{
|
|
if (index_ == 0)
|
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
|
throw std::runtime_error ("throw from iterator comparison");
|
|
#else
|
|
assert(false);
|
|
#endif
|
|
else
|
|
--index_;
|
|
}
|
|
bool atEndL = current_ == end_;
|
|
bool atEndR = rhs.current_ == rhs.end_;
|
|
if (atEndL != atEndR) return false; // one is at the end (or empty), the other is not.
|
|
if (atEndL) return true; // both are at the end (or empty)
|
|
return current_ == rhs.current_;
|
|
}
|
|
|
|
private:
|
|
const T* begin_;
|
|
const T* end_;
|
|
const T* current_;
|
|
ThrowingAction action_;
|
|
mutable size_t index_;
|
|
};
|
|
|
|
template <typename T>
|
|
bool operator== (const ThrowingIterator<T>& a, const ThrowingIterator<T>& b)
|
|
{ return a.operator==(b); }
|
|
|
|
template <typename T>
|
|
bool operator!= (const ThrowingIterator<T>& a, const ThrowingIterator<T>& b)
|
|
{ return !a.operator==(b); }
|
|
|
|
template <typename T>
|
|
struct NonThrowingIterator {
|
|
typedef std::bidirectional_iterator_tag iterator_category;
|
|
typedef ptrdiff_t difference_type;
|
|
typedef const T value_type;
|
|
typedef const T * pointer;
|
|
typedef const T & reference;
|
|
|
|
// Constructors
|
|
NonThrowingIterator ()
|
|
: begin_(nullptr), end_(nullptr), current_(nullptr) {}
|
|
NonThrowingIterator (const T *first, const T* last)
|
|
: begin_(first), end_(last), current_(first) {}
|
|
NonThrowingIterator (const NonThrowingIterator &rhs)
|
|
: begin_(rhs.begin_), end_(rhs.end_), current_(rhs.current_) {}
|
|
NonThrowingIterator & operator= (const NonThrowingIterator &rhs) TEST_NOEXCEPT
|
|
{
|
|
begin_ = rhs.begin_;
|
|
end_ = rhs.end_;
|
|
current_ = rhs.current_;
|
|
return *this;
|
|
}
|
|
|
|
// iterator operations
|
|
reference operator*() const TEST_NOEXCEPT
|
|
{
|
|
return *current_;
|
|
}
|
|
|
|
NonThrowingIterator & operator++() TEST_NOEXCEPT
|
|
{
|
|
++current_;
|
|
return *this;
|
|
}
|
|
|
|
NonThrowingIterator operator++(int) TEST_NOEXCEPT
|
|
{
|
|
NonThrowingIterator temp = *this;
|
|
++(*this);
|
|
return temp;
|
|
}
|
|
|
|
NonThrowingIterator & operator--() TEST_NOEXCEPT
|
|
{
|
|
--current_;
|
|
return *this;
|
|
}
|
|
|
|
NonThrowingIterator operator--(int) TEST_NOEXCEPT
|
|
{
|
|
NonThrowingIterator temp = *this;
|
|
--(*this);
|
|
return temp;
|
|
}
|
|
|
|
bool operator== (const NonThrowingIterator &rhs) const TEST_NOEXCEPT
|
|
{
|
|
bool atEndL = current_ == end_;
|
|
bool atEndR = rhs.current_ == rhs.end_;
|
|
if (atEndL != atEndR) return false; // one is at the end (or empty), the other is not.
|
|
if (atEndL) return true; // both are at the end (or empty)
|
|
return current_ == rhs.current_;
|
|
}
|
|
|
|
private:
|
|
const T* begin_;
|
|
const T* end_;
|
|
const T* current_;
|
|
};
|
|
|
|
template <typename T>
|
|
bool operator== (const NonThrowingIterator<T>& a, const NonThrowingIterator<T>& b) TEST_NOEXCEPT
|
|
{ return a.operator==(b); }
|
|
|
|
template <typename T>
|
|
bool operator!= (const NonThrowingIterator<T>& a, const NonThrowingIterator<T>& b) TEST_NOEXCEPT
|
|
{ return !a.operator==(b); }
|
|
|
|
#undef DELETE_FUNCTION
|
|
|
|
#endif // ITERATORS_H
|