blob: a54787af1b6327911595ef41fb6808403c0e0b6b [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// 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